题意:
输入a、b, 求a/b 可以由多少个埃及分数组成。
埃及分数是形如1/a , a是自然数的分数。
如2/3 = 1/2 + 1/6, 但埃及分数中不允许有相同的 ,如不可以2/3 = 1/3 + 1/3.
求出可以表达a/b个数最少埃及分数方案, 如果个数相同则选取最小的分数最大。
#include <bits/stdc++.h> #define LL long long using namespace std; int maxd; long long v[1234],ans[1234]; bool better(int d){ for(int i = d; i >= 0; i--){ if(v[i] != ans[i]){ //如果这一层没有标记, 或者标记的数小于传入的v[i], 说明当前为更优解 return ans[i] == -1 || v[i] < ans[i]; } return false; } } //求满足 1/c <= a/b 最大的1/c, 即最小的c inline int get_first(LL a,LL b){ return b/a+1; } //当前深度为d, 分母不能小于from, 分数之和为aa, bb bool dfs(int d, int from, LL aa, LL bb){ if( d == maxd){ if(bb % aa) return false; v[d] = bb / aa; if(better(d)) memcpy(ans, v , sizeof(v)); return true; } bool ok = false; from = max(from, get_first(aa, bb)); // 如果上一次递归的from不符合aa/bb最小的分母, 则取get_first(aa,bb) for(int i = from; ; i++) { // 剪枝:如果剩下的maxd+1-d个分数全部都是1/i,加起来仍然不超过aa/bb,则无解 if(bb * (maxd+1-d) <= i * aa) break; v[d] = i; // 计算aa/bb - 1/i,设结果为a2/b2 LL b2 = bb*i; LL a2 = aa*i - bb; LL g = __gcd(a2, b2); // 以便约分 if(dfs(d+1, i+1, a2/g, b2/g)) ok = true; } return ok; } int main(){ int a, b; scanf("%d %d", &a, &b); for(maxd = 1; ;maxd++){ //这里可以做一些限制, 层数上限不一定为infinite memset(ans, -1, sizeof(ans)); if(dfs(0,get_first(a,b),a,b)) { break; } } for(int i = 0; i <= maxd; i++) printf("%lld ", ans[i]); }