codevs 1288 埃及分数
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 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 Description
a b
输出描述 Output Description
若干个数,自小到大排列,依次是单位分数的分母。
样例输入 Sample Input
19 45
样例输出 Sample Output
5 6 18
数据范围及提示 Data Size & Hint
迭代加深+剪枝
#include <cstring> #include <cstdio> typedef long long LL; const LL inf = 2147483647; bool flag; LL a,b,len,ans[100],ls[100]; inline LL max(LL a,LL b) {return a>b?a:b;} LL gcd(LL m,LL n) {return !n?m:gcd(n,m%n);} void dfs(LL now,LL from,LL m,LL n) { if(now>len) return; if(m==1&&n>ls[now-1]) { ls[now]=n; if(!flag||ls[now]<ans[now]) { for(LL i=1;i<=now;++i) ans[i]=ls[i]; } flag=1; return; } from=max(from,n/m+1); for(LL i=from;;++i) { if(n*(len-now+1)<=m*i) break; ls[now]=i; LL Gcd=gcd(i*m-n,i*n); dfs(now+1,i+1,(i*m-n)/Gcd,(i*n)/Gcd); } } int main() { scanf("%lld%lld",&a,&b); LL Gcd=gcd(a,b); a/=Gcd,b/=Gcd; flag=false; ls[0]=1; for(len=1;;++len) { dfs(1,b/a+1,a,b); if(flag) break; } for(LL i=1;i<=len;++i) i==len?printf("%lld\n",ans[i]):printf("%lld ",ans[i]); return 0; }
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。