[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;
} 
posted @ 2018-11-08 15:33  昤昽  阅读(208)  评论(0编辑  收藏  举报