1. 程式人生 > >[題解]「一本通 1.3 練習 1」埃及分數

[題解]「一本通 1.3 練習 1」埃及分數

埃及分數題目連結

這道題比較經典。

演算法:迭代加深+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 
#define
R 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; } //迭代加深 //上下界剪枝