其他分享
首页 > 其他分享> > 埃及分数 单位分数

埃及分数 单位分数

作者:互联网

#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;
}

标签:分数,埃及,aa,return,bb,LL,deep,单位,ans
来源: https://blog.csdn.net/qq_41575431/article/details/118655661