[Codevs 1228]埃及分数

Egyptian Fraction

第一道迭代加深搜索,《算法竞赛入门经典》上的例题。
注意分母这个数字可能很大,所以要用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;
} 

猜你喜欢

转载自www.cnblogs.com/Corona09/p/9928620.html