埃及分数 单位分数

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const LL BIG=1000;

LL a, b;
LL ans[BIG],now[BIG],maxd;

LL gcd(LL a, LL b)
{
	return b == 0 ? a : gcd(b, a % b);
}

LL find_best(LL a, LL b)//满足1/i<=a/b的最小i,i>=b/a
{
	return b / a + 1;
}

bool better(LL depth)
{
	for (LL d = depth; d >= 1; d--)
		if (now[d] != ans[d])
			return ans[d] == -1 || now[d] < ans[d];
            //如果此深度的ans没有解,或者有解但是解的最小的分数的分母没有现在的小,就找到了更好的,就替换
	return false;
}

bool dfs(LL deep,LL next,LL aa,LL bb)
{  //当前深度为deep,加下来的分母不能小于next,接下来的分式之和恰好为aa/bb
	bool flag;
	if (deep == maxd)//如果此时单位分数的个数到了枚举最多的限制
	{
		if (bb % aa)
			return false;//bb不能整除aa
		now[deep] = bb / aa;//取分母
		if (better(deep))
			memcpy(ans, now, sizeof(LL)*(deep+1));//找到了更优的解,更新ans
		return true;
	}
	flag = false;
	next = max(next, find_best(aa, bb));
	for (LL i = next;; i++)
	{
		if ((maxd - deep + 1) * bb <= i * aa)
	    /*从当前深度的接下来(maxd + 1 - deep)项分式,(从当前的没定的第deep个分数,到最后的maxd个分数,共(maxd + 1 - deep)个)
	    如果(1 / i)* (maxd + 1 - deep)还凑不够aa / bb,则需要剪枝*/
			break;
		now[deep] = i;
		//计算(aa/bb) - (1/i),通分后的分母是bb*i,分子是aa*i-bb
		LL b2 = bb * i;
		LL a2 = aa * i - bb;
		LL g = gcd(a2, b2);
		if (dfs(deep + 1, i+1, a2 / g, b2 / g))
			flag = true;
	}
	return flag;

}

int main()
{
	scanf("%lld%lld", &a, &b);
	int check = 0;
	for (maxd = 1;; maxd++)
	{
		memset(ans, -1, sizeof(ans));
		if (dfs(1, find_best(a, b), a, b))
		{
			check = 1;
			if (check)
			{
				for (int i = 1; i <= maxd - 1; i++)
				{
					printf("%lld ", ans[i]);
				}
				printf("%lld\n", ans[maxd]);
			}
			break;
		}
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值