topcoder吧 关注:404贴子:391
  • 3回复贴,共1

一道Google code jam 2019 Round 2 的题目

只看楼主收藏回复

题目是求一个位于开区间(lowBound, highBound)内的最佳分数(最佳分数是指分子、分母尽可能取小的正整数)比如 2/3 在(0,1) 区间内,但它不是最佳分数,1/2 才是最佳分数。 再比如:1/2 在(0,2)区间内,但它不是最佳分数,1/1 才是。
原题如下:
Muriel is on the path to discovering two new elements that she has named Codium and Jamarium. She has not been able to isolate them yet, but she wants to start investigating some important properties, like their atomic weights, by indirect means. Since Muriel is working with a single isotope of Codium and a single isotope of Jamarium, their atomic weights are strictly positive integers.
Muriel managed to create N different molecules, each of which contains one or more atoms of Codium and one or more atoms of Jamarium, and no other elements. For each molecule, she knows how many atoms of each element are present in it. The molecular weight of a molecule is the sum of the atomic weights of all the atoms it contains.
As a first step, Muriel sorted the molecules by strictly increasing molecular weight. Now she wants to find out possible integer values for the atomic weights of both Codium and Jamarium that are consistent with the ordering. Since she is aware there could be many consistent pairs of values, she wants one that minimizes the atomic weight of Codium. If there are multiple pairs in which Codium's atomic weight is minimum, she wants the one in which Jamarium's atomic weight is minimum。
Input
The first line of the input gives the number of test cases, T. T test cases follow. The first line of a test case contains a single integer N, the number of molecules. Each of the next N lines describes a different molecule with two integers Ci and Ji that represent the number of Codium and Jamarium atoms in the i-th molecule, respectively. The molecules are given in strictly increasing order of molecular weight.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1), and y is IMPOSSIBLE (in uppercase) if there is no pair of integer atomic weights that would make the order of the molecules strictly increasing in molecular weight. Otherwise, y should be two integers c j where c is the atomic weight of Codium and j is the atomic weight of Jamarium, chosen according to the rules above.


1楼2019-06-22 21:07回复
    以下是3组样例:

    In Sample Case #1, the difference between the last two molecules is having an extra atom of one element or the other. Given that the one having the extra Codium is heavier overall, we conclude that Codium must be heavier than Jamarium. The values 2 and 1 for the atomic weights of Codium and Jamarium make the molecular weights 1 × 2 + 1 × 1 = 3, 1 × 2 + 2 × 1 = 4, and 2 × 2 + 1 × 1 = 5, respecting the strict ordering. Since Codium is heavier than Jamarium in this case, 2 is Codium's minimum atomic weight, and 1 is of course Jamarium's minimum atomic weight.
    Let a, b, c and d be the molecular weights of the molecules in Sample Case #2, in increasing order of molecular weight. By their atom contents, d = 2 × a and c = 2 × b. It follows from a < b that d = 2 × a < 2 × b = c, which means there is no pair of values for the atomic weights that would make the ordering strictly increasing.
    In Sample Case #3, notice that the molecules happen to be sorted in strictly increasing order of total number of atoms. Therefore, assigning both elements an atomic weight of 1 makes the atomic weights be sorted in strictly increasing order.


    2楼2019-06-22 21:08
    回复
      我是用连分数来求“区间内最佳分数”。奇怪的是,系统判定为WA,但我随机生成几千组数据,将我的代码的输出结果,与另一个选手的输出结果进行比对,完全一致。
      不知道问题出在哪里:
      import java.util.*;
      public class Solution{
      public static void main(String[] args){
      Scanner in = new Scanner(System.in);
      int T = in.nextInt();
      for(int cas = 1; cas <= T; cas++){
      int n = in.nextInt();
      int[][] pair = new int[n][2];
      for(int i = 0; i < n; i++){
      pair[i][0] = in.nextInt();
      pair[i][1] = in.nextInt();
      }
      boolean stop = false;
      Rational lowBound = new Rational(0L, 1L);
      Rational highBound = new Rational(1000000009L, 1L);
      for(int i = 0; i < n; i++){
      for(int j = i+1; j < n; j++){
      int dis1 = pair[j][0] - pair[i][0];
      int dis2 = pair[j][1] - pair[i][1];
      if(dis1 <= 0 && dis2 <= 0){
      stop = true;
      break;
      }
      if(dis1 >= 0 && dis2 >= 0)
      continue;
      if(dis2 > 0)
      lowBound = updatelowBound((long)(-dis1),(long)(dis2), lowBound);
      else if(dis1 > 0)
      highBound = updatehighBound((long)(dis1),(long)(-dis2), highBound);
      if(lowBound.compareTo(highBound) >= 0){
      stop = true;
      break;
      }
      }
      if(stop)
      break;
      }
      if(stop){
      System.out.println("Case #"+cas+": IMPOSSIBLE");
      continue;
      }
      List<Integer> cf1 = continuedFraction(lowBound);
      List<Integer> cf2 = continuedFraction(highBound);
      List<Integer> ans = new ArrayList<>();
      boolean isSubList = true;
      for(int i = 0; i < Math.min(cf1.size(),cf2.size()); i++){
      if(cf1.get(i) != cf2.get(i)){
      isSubList = false;
      break;
      }
      }
      if(isSubList){
      if(cf1.size() < cf2.size()){
      if(cf1.size() % 2 == 1)
      cf1.add(cf2.get(cf1.size()) + 1);
      else
      cf1.add(cf2.get(cf1.size()) - 1);
      ans = cf1;
      }
      else{
      if(cf2.size() % 2 == 1)
      cf2.add(cf1.get(cf2.size()) - 1);
      else
      cf2.add(cf1.get(cf2.size()) + 1);
      ans = cf2;
      }
      }
      for(int i = 0; !isSubList && i < Math.min(cf1.size(),cf2.size()); i++){
      int min = cf1.get(i);
      List<Integer> bigger = new ArrayList<>();
      List<Integer> smaller = new ArrayList<>();
      if(cf1.get(i) < cf2.get(i)){
      min = cf1.get(i);
      bigger = cf2;
      smaller = cf1;
      }
      else if(cf1.get(i) > cf2.get(i)){
      min = cf2.get(i);
      bigger = cf1;
      smaller = cf2;
      }
      else{
      ans.add(min);
      continue;
      }
      if(Math.abs(cf1.get(i) - cf2.get(i)) > 1){
      ans.add(min + 1);
      break;
      }
      if(Math.abs(cf1.get(i) - cf2.get(i)) == 1){
      if(bigger.size() > i+1){
      ans.add(min + 1);
      }
      else if(smaller.size() > i+1 && smaller.get(i+1) == 2){
      ans.add(min); ans.add(1); ans.add(2);
      }
      else {
      ans.add(min); ans.add(2);
      }
      break;
      }
      }
      long fz = 0; long fm = 1; long temp = 0;
      for(int i = ans.size() - 1; i >= 0; i--){
      fz += ans.get(i)*fm;
      temp = fz;
      fz = fm;
      fm = temp;
      }
      if(ans.get(0) > 0){ // Wj/Wc > 1
      System.out.println("Case #"+cas+": "+Math.min(fz,fm)+" "+Math.max(fz,fm));
      }
      else{ // Wj/Wc < 1
      System.out.println("Case #"+cas+": "+Math.max(fz,fm)+" "+Math.min(fz,fm));
      }
      }
      }
      static List<Integer> continuedFraction(Rational r){ // 将分数转化为连分数的形式
      List<Integer> list = new ArrayList<>();
      long fz = r.fenzi;
      long fm = r.fenmu;
      while(fm != 0){
      list.add((int)(fz/fm));
      long temp = fz % fm;
      fz = fm;
      fm = temp;
      }
      return list;
      }
      static class Rational{
      long fenmu, fenzi;
      public Rational(long x, long y){
      long g = getGCD(x,y);
      fenzi = x/g;
      fenmu = y/g;
      }
      public int compareTo(Rational r){
      long g = getGCD(fenmu, r.fenmu);
      long fz1 = fenzi * (r.fenmu/g);
      long fz2 = r.fenzi * (fenmu/g);
      return Long.compare(fz1,fz2);
      }
      }
      static long getGCD(long a, long b){
      if(a % b == 0)
      return b;
      else
      return getGCD(b, a % b);
      }
      static Rational updatelowBound(long a, long b, Rational r){
      Rational s = new Rational(a,b);
      if(s.compareTo(r) > 0)
      return s;
      else
      return r;
      }
      static Rational updatehighBound(long a,long b,Rational r){
      Rational s = new Rational(a,b);
      if(s.compareTo(r) < 0)
      return s;
      else
      return r;
      }
      }


      3楼2019-06-22 21:11
      回复
        LZ好,请问可以介绍一下用连分数解这道题的思路吗,我看了题解,没搞明白怎么用连分数来求“分母不大于某个数的所有分数距离一个数的最小值”。谢谢~


        4楼2019-08-28 22:22
        回复