zoukankan      html  css  js  c++  java
  • UVA_埃及分数(Hard Version) UVA 12588

    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("
    ");
     99     
    100  }    
    101  return 0;
    102 }
    No Pain , No Gain.
  • 相关阅读:
    ubuntu 搭建 php 环境
    【转】送给和我一样曾经浮躁过的PHPer程序猿,希望有帮助
    thinkphp iis下去掉index.php
    windows定时执行PHP的技巧
    js 生成随机数字的方法
    Linux下crontab命令的用法
    收藏下(设为收藏,设为首页)
    C#扩展方法的理解
    Win7 访问共享时输入正确密码仍然提示密码错误
    SQL Server 获取插入记录后的自动编号ID
  • 原文地址:https://www.cnblogs.com/Xiper/p/4467774.html
Copyright © 2011-2022 走看看