埃及分数 单位分数
作者:互联网
#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