在古埃及,人们使用单位分数的和(形如 的,
是自然数)表示一切有理数。如:
,但不允许
,因为加数中有相同的。对于一个分数
,表示方法有很多种,但是哪种最好呢?首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。如:
最好的是最后一种,因为 比
都大。
注意,可能有多个最优解。如:
由于方法一与方法二中,最小的分数相同,因此二者均是最优解。
给出 a,b,编程计算最好的表达方式。保证最优解满足:最小的分数 ≥。
输入描述
一行两个整数,分别为 a 和 b 的值。
输出描述
输出若干个数,自小到大排列,依次是单位分数的分母。
样例输入 1
19 45
样例输出 1
5 6 18
提示
数据范围与提示
0<a<b<1000
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define ll long long
#include <algorithm>
using namespace std;
ll a,b,depth,temp[101]= {0},ans[101]= {0};
bool flag=0;
ll gcd(ll a,ll b) {
return b==0?a:gcd(b,a%b);
}
void dfs(ll newa,ll newb,ll step) {
if (step+1==depth) { //对应的分母个数
if (newa==1) { //最后一个分子是1
temp[step+1]=newb;
flag=1;
//最后一个分母第一次赋值,或者比之前的分母小,更新答案
if (temp[step+1]<ans[step+1]||ans[step+1]==0)
memcpy(ans,temp,sizeof(temp));
}
return;
}
ll first=newb%newa?newb/newa+1:newb/newa;
//起始值要么是上一个数字+1,要么是ceil();终点是分母的最大值
for(ll i=max(temp[step]+1,first); i<=ceil(newb/newa)*(depth-step); i++) {
temp[step+1]=i;
ll nexta,nextb,g;
nexta=newa*i-newb,nextb=newb*i;
g=gcd(nexta,nextb);
dfs((ll)nexta/g,(ll)nextb/g,step+1);
}
}
int main() {
scanf("%lld %lld",&a,&b);
ll g=gcd(a,b);
temp[0]=1;
for(depth=1;; depth++) {
dfs((ll)a/g,(ll)b/g,0);
if (flag) break;
}
for(int i=1; i<=depth; i++)
printf("%lld ",ans[i]);
return 0;
}