题解:P1763 埃及分数
dangerous_tDp · · 题解
还能交题解肯定得蹭啊。
发现给的题面较为困难,于是直接考虑爆搜,但是这样深搜显然超时,而宽搜状态数会超内存,故而进行迭代加深搜索(即逐层提高限制进行深搜)以降低复杂度。
枚举
我们记
但是这样做还是太粗糙了,无法通过,考虑更加精细的搜索。
首先当
其次,当
注意为了得到最简的分数每次搜索需要约分。
:::success[code]
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e7;
int dep = 1, st[11], ans[11], f;
int gcd(int a, int b){
if (!a || !b)return a | b;
int az = __builtin_ctzll(a), bz = __builtin_ctzll(b), z = az < bz ? az : bz;
a >>= az;
do{
b >>= bz;
if (a > b){int t = a;a = b, b = t;}
b -= a, bz = __builtin_ctzll(b);
}while (b);
return a << z;
}void dfs(int a, int b, int x){
if (x > dep)return;
if (a == 1 && b > st[x - 1]){
st[x] = b;
if (!f || b < ans[dep])
for (int i = 1; i <= dep; i ++)ans[i] = st[i];
f = 1;return;
}if (x == dep - 1){
for (int i = ceil(4.0 * b / a / a); ; i ++){
int z = a * i, d = z * z - 4 * b * i, t = sqrt(d), g = -1;
if (t * t == d)g = t;else if ((t - 1) * (t - 1) == d)g = t - 1;
else if ((t + 1) * (t + 1) == d)g = t + 1;
int k = z - g >> 1, y = z + g >> 1;
if (y > N || (f && y >= ans[dep]))break;
if (g <= 0 || (z + g & 1))continue;
st[dep - 1] = k, st[dep] = y;
if (!f || y < ans[dep]){
for (int i = 1; i <= dep; i ++)ans[i] = st[i];
f = 1;
}break;
}return;
}int l = max((b + a - 1) / a, st[x - 1] + 1), r = (dep - x + 1) * b / a;
if (f && r >= ans[dep])r = ans[dep] - 1;r = min(r, N);
for (int i = l; i <= r; i ++){
st[x] = i;
int num = a * i - b, den = b * i, g = gcd(abs(num), den);
dfs(num / g, den / g, x + 1);
if (f && i >= ans[dep])break;
}
}signed main(){
int a, b, c;
cin >> a >> b, c = gcd(a, b), a /= c, b /= c, st[0] = 1;
for (dep = 1; ; dep ++){
f = 0, dfs(a, b, 1);
if (f){
for (int i = 1; i <= dep; i ++)cout << ans[i] << " ";
return 0;
}
}return 0;
}
:::
鸣谢:感谢 HITUO 提供了代码基础框架和调题动力,HRPA 提供了 gcd 板子,具体的开根做法参考了此篇题解。