1. 程式人生 > >codevs1288 埃及分數

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; }