[CODEVS 1288]埃及分数

Description

在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好。 如: 19/45=1/3 + 1/12 + 1/180 19/45=1/3 + 1/15 + 1/45 19/45=1/3 + 1/18 + 1/30, 19/45=1/4 + 1/6 + 1/180 19/45=1/5 + 1/6 + 1/18. 最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。 给出a,b(0<a<b<1000),编程计算最好的表达方式。

Input

a b

Output

若干个数,自小到大排列,依次是单位分数的分母。

Sample Input

19 45

Sample Output

5 6 18

题解

迭代的入门经典题...然而我现在才做...

我们将深度迭代,搜索。

由于要使最小的分数最大,所以我们要边搜的时候记录当前状况下的最优解。

加个$A*$。

我们用估价函数算出枚举分母的范围区间。

注意开$int$会爆。

 1 #include<map>
 2 #include<ctime>
 3 #include<cmath>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<string>
 8 #include<vector>
 9 #include<cstring>
10 #include<cstdlib>
11 #include<iostream>
12 #include<algorithm>
13 #define LL long long
14 #define RE register
15 #define IL inline
16 using namespace std;
17 const LL INF=~0u>>1;
18 
19 LL keep[100],ans[100];
20 LL gcd(LL a,LL b) {return b ? gcd(b,a%b):a;}
21 
22 LL a,b,lim;
23 
24 void Dfs(LL cen,LL x,LL y)
25 {
26     if (cen>lim) return;
27     LL g=gcd(x,y);x/=g;y/=g;
28     if (x==1&&y>keep[cen-1])
29     {
30         keep[cen]=y;
31         if (keep[cen]<ans[cen]) memcpy(ans,keep,sizeof(ans));
32         return;
33     }
34     LL s=y/x;
35     if (keep[cen-1]>=s) s=keep[cen-1]+1;
36     LL t=y*(lim-cen+1)/x;
37     for (LL i=s;i<=t;i++)
38     {
39         keep[cen]=i;
40         Dfs(cen+1,i*x-y,y*i);
41     }
42 }
43 
44 int main()
45 {
46     scanf("%lld%lld",&a,&b);
47     for (;;lim++)
48     {
49         ans[lim]=INF;
50         Dfs(1,a,b);
51         if (ans[1]>0&&ans[1]<INF)
52         {
53             for (RE LL i=1;i<=lim;i++) printf("%lld ",ans[i]);
54             return 0;
55         }
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/NaVi-Awson/p/7373406.html