题目描述 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
一个迭代加深模版题,然而我默默地打了一个晚上。。
主要注意剪枝和数据要开longlong,因为没开longlong在codves上最后一个点爆了
#include<bits/stdc++.h> #define ll long long using namespace std; ll a,b,maxd,ans[1010],tmp[1010]; ll gcd(ll x,ll y){ return y?gcd(y,x%y):x; } bool dfs(ll a,ll b,ll step){ if(step==maxd){ if(a==1){ if(b>tmp[step-1]){ tmp[step]=b; if(tmp[step]<ans[step]){ for(int i=1;i<=step;i++) ans[i]=tmp[i]; } } return 1; } else return 0; } if(a/(b*(maxd-step+1))>ans[maxd]) return 0; bool ok=0; for(int i=max(tmp[step-1]+1,b/a);i<=b*(maxd-step+1)/a;i++){ if(b>a*i) continue; tmp[step]=i; ll c=gcd(a*i-b,b*i); if(dfs((a*i-b)/c,(b*i)/c,step+1)) ok=1; } if(!ok)return 0;return 1; } int main(){ scanf("%lld%lld",&a,&b); ll c=gcd(a,b); a/=c;b/=c; if(a==1){ printf("%lld",b); return 0; } for(int i=1;i<=1000;i++) ans[i]=10000000; for(maxd=2;;maxd++){ memset(tmp,0,sizeof(tmp));tmp[0]=1; if(dfs(a,b,1)){ for(int i=1;i<=maxd;i++) printf("%d ",ans[i]);return 0; } } }
原文地址:https://www.cnblogs.com/plysc/p/10321420.html
时间: 2024-10-28 14:47:53