codevs1288 埃及分数
题目描述:
在古埃及,人们使用单位分数的和(形如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),编程计算最好的表达方式。
题解:
搜索。迭代加深搜索,也称IDDFS。
搞一搞边界剪一剪枝。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ll long long ll a,b; ll ans[1000500],tmp[1000500]; ll gcd(ll x,ll y) { if(!y)return x; return gcd(y,x%y); } ll aa,bb,Gcd,i,lim; void dfs(ll u,ll dep,ll la,ll lb) { if(dep==lim) { if(la==1&&u<=lb) { tmp[lim]=lb; if(lb<=ans[lim]||!ans[lim]) { for(i=1;i<=lim;i++) ans[i]=tmp[i]; } } return ; } if(u*la>lb*(lim-dep+1))return ; if(ans[lim]&&u>ans[lim])return ; dfs(u+1,dep,la,lb); tmp[dep]=u; aa = la*u-lb,bb = lb*u; if(aa<0)return ; Gcd = gcd(aa,bb); aa/=Gcd,bb/=Gcd; dfs(u+1,dep+1,aa,bb); } int main() { scanf("%lld%lld",&a,&b); Gcd = gcd(a,b); a/=Gcd,b/=Gcd; for(lim=1;;lim++) { dfs(b/a,1,a,b); if(ans[1])break; } for(i=1;ans[i];i++) printf("%lld ",ans[i]); printf("\n"); return 0; }