【CodeVS 1288】埃及分数

http://codevs.cn/problem/1288/
loli秘制面向高一的搜索,好难啊QAQ
我本来想按照分母从大到小搜,因为这样分母从小到大枚举到的第一个可行方案就是最优方案。
但貌似会T。。。
所以按照分母从小往大搜,分母得有个上界。
设分母为(num),则(frac{step}{num}geqfrac{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
", 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('
');
	}
	return 0;
}
原文地址:https://www.cnblogs.com/abclzr/p/6071021.html