【CodeVS 1288】埃及分数
http://codevs.cn/problem/1288/
loli秘制面向高一的搜索,好难啊QAQ
我本来想按照分母从大到小搜,因为这样分母从小到大枚举到的第一个可行方案就是最优方案。
但貌似会T。。。
所以按照分母从小往大搜,分母得有个上界。
设分母为\(num\),则\(\frac{step}{num}\geq\frac{a}{b},num \leq \frac{b·step}a\),且\(\frac ab-\frac 1{num}=\frac{a·num-b}{b·num}\)
\(step\)为IDA*枚举的步数。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int step;
ll g, ans[1003], num[1003];
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
void dfs(ll a, ll b, int down, int tmp) {
if (a < 0) return;
g = gcd(a, b); a /= g; b /= g;
if (tmp == step) {
if (a != 1 || num[tmp - 1] >= b) return;
num[tmp] = b;
if (!ans[1] || num[tmp] < ans[tmp])
memcpy(ans, num, sizeof(ll) * (step + 1));
num[tmp] = 0;
return;
}
int up = (int) floor(1.0 * b * step / a) + 1;
for (int i = down; i <= up; ++i) {
num[tmp] = i;
dfs(a * i - b, b * i, i + 1, tmp + 1);
}
num[tmp] = 0;
}
int main() {
ll a, b; int up;
scanf("%lld%lld", &a, &b);
if (b % a == 0) {
printf("%lld\n", b / gcd(a, b));
return 0;
}
for (step = 2; ; ++step) {
up = (int) floor(1.0 * b * step / a);
for (int i = 2; i <= up; ++i) {
num[1] = i;
dfs(a * i - b, b * i, i + 1, 2);
}
num[1] = 0;
if (ans[1]) break;
}
for (int i = 1; i <= step; ++i) {
printf("%lld", ans[i]);
if (i != step) putchar(' ');
else putchar('\n');
}
return 0;
}
NOI 2017 Bless All