[題解]「一本通 1.3 練習 1」埃及分數
阿新 • • 發佈:2018-11-02
這道題比較經典。
演算法:迭代加深+IDA*
優化:
1.迭代加深
2.確定從小到大的搜尋順序
3.確定搜尋上下界
(1)以i為分母的數字不能大於a/b.
(2)如果後面的數字都以i為分母仍然<=a/b,退出。
細節:
(1)在通分過程中會爆int。
程式碼:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll unsigned long long #defineR register using namespace std; const int N=1e5+5; ll ans_a,ans_b,ans[N],lin[N],k,flag,vis[N]; inline ll gcd(R ll a,R ll b){ if(b==0)return a; return gcd(b,a%b); } inline void dfs(R ll x,R ll a,R ll b,ll lst)//正在填第幾個 { if(x==k){ if(b%a==0) { flag=1; ans[k]=b/a; if(ans[k]<lin[k]) for(R ll i=1;i<=k;i++) lin[i]=ans[i]; } return; } for(R ll i=lst+1;i;i++) { if((k-x+1)*b<=a*i)break; if(i*a<b)continue; R ll zi=i*a-b; R ll mu=i*b; R ll g=gcd(zi,mu); ans[x]=i; dfs(x+1,zi/g,mu/g,i); ans[x]=0; } } int main(){ scanf("%lld%lld",&ans_a,&ans_b);cn k=0; k=gcd(ans_a,ans_b); ans_a/=k; ans_b/=k; k=0; memset(lin,127,sizeof(lin)); while(!flag) { k++; dfs(1,ans_a,ans_b,0); } for(R ll i=1;i<=k;i++) printf("%lld ",lin[i]); return 0; } //迭代加深 //上下界剪枝