Problem E
Eg[y]ptian Fractions (HARD version)
Given a fraction a/b, write it as a sum of different Egyptian fraction. For
example, 2/3=1/2+1/6.
There is one restriction though: there are k restricted integers that should not
be used as a denominator. For example, if we can't use 2~6, the best solution is:
2/3=1/7+1/8+1/9+1/12+1/14+1/18+1/24+1/28
The number of terms should be minimized, and then the large denominator should be
minimized. If there are several solutions, the second largest denominator should
be minimized etc.
Input
The first line contains the number of test cases T(T<=100). Each test case begins
with three integers a, b, k(2<=a<b<=876, 0<=k<=5, gcd(a,b)=1). The next line
contains k different positive integers not greater than 1000.
Output
For each test case, print the optimal solution, formatted as below.
Sample Input
5 2
3 0
19 45 0
2 3 1 2
5 121 0
5 121 1 33
Output for the Sample Input
Case 1: 2/3=1/2+1/6
Case 2: 19/45=1/5+1/6+1/18
Case 3: 2/3=1/3+1/4+1/12
Case 4: 5/121=1/33+1/121+1/363
Case 5: 5/121=1/45+1/55+1/1089
Extremely Important Notes
It's not difficult to see some inputs are harder than others. For example, these
inputs are very hard input for every program I have:
596/829=1/2+1/5+1/54+1/4145+1/7461+1/22383
265/743=1/3+1/44+1/2972+1/4458+1/24519
181/797=1/7+1/12+1/2391+1/3188+1/5579
616/863=1/2+1/5+1/80+1/863+1/13808+1/17260
22/811=1/60+1/100+1/2433+1/20275
732/733=1/2+1/3+1/7+1/45+1/7330+1/20524+1/26388
However, I don't want to give up this problem due to those hard inputs, so I'd
like to restrict the input to "easier" inputs only. I know that it's not a perfect
problem, but it's true that you can still have fun and learn something, isn't it?
Some tips:
Watch out for floating-point errors if you use double to store intermediate
result. We didn't use double.
Watch out for arithmetic overflows if you use integers to store intermediate
result. We carefully checked our programs for that.

 

解题报告

迭代加深搜索。。注意带入上一个的分母,并且保证升序就可以辣,注意不要使用受限制的分母

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 typedef long long LL;
  6 using namespace std;
  7 LL ban[5];
  8 int ban_num;
  9 int maxd;
 10 LL ans[1000];
 11 LL temp[1000]; 
 12 
 13 LL gcd(LL a,LL b)
 14 {
 15  return b == 0 ? a : gcd(b,a%b);    
 16 }
 17 
 18 
 19 
 20 
 21 
 22 /* gs 保证升序            */
 23 bool dfs(LL a,LL b,LL gs,int d)
 24 {
 25  if (d == maxd)
 26   {
 27       if (b % a || b <= temp[d-1]) return false;
 28       /*Check Last Num                     */
 29       for(int i = 0 ;i<ban_num;++i)
 30        if (b == ban[i])
 31         return false;
 32       temp[d] = b;
 33       int ok = 0;
 34       for(int i = d;i>=0;--i)
 35        if(ans[i] == -1)
 36         {
 37             ok = 1;
 38             break;
 39         }        
 40      else if(ans[i] != temp[i])
 41       {
 42           if (temp[i] < ans[i])
 43            ok = 1;
 44            break;
 45       }
 46     if (ok)
 47      memcpy(ans,temp,sizeof(LL) * (d+1));
 48     return true;
 49   }
 50  bool c = false;
 51  LL start = max(b/a + 1,gs);
 52  for(int i = start;;++i)
 53   {
 54       int ok = 1;
 55       if ( a * i > b*(maxd - d + 1)) break;
 56       for(int j = 0;j<ban_num;++j)
 57           if (i == ban[j])
 58           {
 59               ok = 0;
 60               break;
 61           }
 62        if (!ok) continue;
 63       LL na = a*i - b;
 64       LL nb = b*i;
 65       LL gc_ = gcd(na,nb);
 66       temp[d] = i;
 67       if (dfs(na/gc_,nb/gc_,i+1,d+1))
 68        c= true;
 69   }
 70  return c;    
 71 }
 72 
 73 
 74 
 75 
 76 
 77 int main(int argc,char * argv[])
 78 {
 79  int T2 = 1;
 80  int T;
 81  cin >> T;
 82  while(T--)
 83  {
 84      memset(ans,-1,sizeof(ans));
 85      LL a,b;
 86      cin >> a >> b >> ban_num;
 87      for(int i = 0 ; i < ban_num;++i)
 88       cin >> ban[i];      
 89     for(int i = 1;;++i)
 90      {
 91          maxd = i;
 92          if (dfs(a,b,0,0))
 93           break;
 94      }
 95     printf("Case %d: %lld/%lld=",T2++,a,b);
 96     for(int i = 0;i<=maxd;++i)
 97      i == 0 ? printf("1/%lld",ans[i]) : printf("+1/%lld",ans[i]);
 98     printf("\n");
 99     
100  }    
101  return 0;
102 }

 

posted on 2015-04-29 23:30  天心散人  阅读(459)  评论(0编辑  收藏  举报