[Codevs 1228]埃及分數
阿新 • • 發佈:2018-11-08
第一道迭代加深搜尋,《演算法競賽入門經典》上的例題。
注意分母這個數字可能很大,所以要用long long
在尋找滿足 \(1/c \leq a/b\) 的最小的 \(c\) 時,可以知道\(c=\lceil a/b \rceil\),注意要將\(a/b\)轉換成double
型別.
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; typedef long long ll; const int MAXD=1000+1; ll ans[MAXD],v[MAXD]; inline ll get_first(ll a,ll b) { for(ll c=1;;c++) { if(a*c>=b) return c; } } inline bool better_ans(int maxd) { if(!ans[maxd] || v[maxd]!=ans[maxd]) return !ans[maxd] || v[maxd]<ans[maxd]; for(int i=1;i<maxd;i++) if(v[i]!=ans[i]) return v[i]<ans[i]; return false; } inline int gcd(ll x,ll y) { return !y?x:gcd(y,x%y); } bool dfs(int d,int maxd,ll from,ll a,ll b) { if(d==maxd) { if(b%a) return false; v[d]=b/a; if(better_ans(maxd)) { memcpy(ans,v,sizeof(v)); } return true; } bool ok=false; from=max(from,get_first(a,b)); for(ll i=from;;i++) { if(b*(maxd+1-d)<=i*a) break; v[d]=i; ll y=b*i,x=a*i-b,g=gcd(max(x,y),min(x,y)); if(dfs(d+1,maxd,i+1,x/g,y/g)) ok=true; } return ok; } int main() { int a,b; scanf("%d %d",&a,&b); if(a==1) { printf("%d",b); return 0; } int maxd; for(maxd=2;;maxd++) { memset(ans,0,sizeof(ans)); if(dfs(1,maxd,get_first(a,b),a,b)) break; } printf("%lld",ans[1]); for(int i=2;i<=maxd;i++) { printf(" %lld",ans[i]); } return 0; }