P1763 埃及分数 题解
P1763 埃及分数
分析
看完这道题,首选
可以枚举
控制搜索深度 Code Show 中的
上述代码如下:
while (!f)
{
S = 100, maxDep++;
while (S < 1e7 && !f)
S = (S << 3) + (S << 1), f = IDDFS(n, m, 1);
}
我们考虑
现申请两个大小为 res,另一个叫 ans,res 帮忙取答案,ans 则准备输出最后最优的结果,设当前层数为
如果已经枚举到最后一层(
由于还要保证最后一个分数最大,即分母最小,还要判断 ans 数组已经有了答案,所以接下里就很简单了
如果上述条件都满足,则只需要用 res 记录一下答案,再用
由于分母递增,若前一分母为
为了能在
即
考虑进一步紧缩下界
如果
类似的在第
综上,
当仅需枚举两个分母时,设剩余两个分母为
可以得出
考虑枚举
当
可以得到
在求解时须验证
考虑
由于
同时在求解时
综上
Code show
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans[25], res[25], S;
int n, m, maxDep;
bool f;
bool IDDFS(ll p, ll q, int dep)
{
if (dep == maxDep)
{
if (p == 1 && q > res[dep - 1] && (q < ans[dep] || !ans[dep]))
{
res[dep] = q;
memcpy(ans, res, sizeof(res));
return true;
}
return false;
}
if (dep == maxDep - 1)
{
for (ll z = (q << 2) / p / p + 1; z < min((S << 1) / p, S * S / q); z++)
{
ll delta = p * p * z * z - (q << 2) * z, s = sqrt(delta);
if (s * s != delta || p * z + s & 1)
continue;
res[dep] = p * z - s >> 1, res[dep + 1] = p * z + s >> 1;
if (res[dep + 1] < ans[dep + 1] || !ans[dep + 1])
{
memcpy(ans, res, sizeof(res));
return true;
}
}
return false;
}
ll l = max(res[dep - 1], (q - 1) / p) + 1LL, r = (maxDep - dep + 1) * q / p;
bool flag = false;
for (int i = l; i < r; i++)
{
ll tx = p * i - q, ty = q * i, g = __gcd(tx, ty);
res[dep] = i;
if (IDDFS(tx / g, ty / g, dep + 1))
flag = true;
}
return flag;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
while (!f)
{
S = 100, maxDep++;
while (S < 1e7 && !f)
S = (S << 3) + (S << 1), f = IDDFS(n, m, 1);
}
for (int i = 1; i <= maxDep; i++)
printf("%lld ", ans[i]);
return 0;
}
注意
本题解由 stonesx 原著,若有意见请发短信给我,作者将及时处理!