题目大意:
在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好。 如: 19/45=1/3 + 1/12 + 1/180 19/45=1/3 + 1/15 + 1/45 19/45=1/3 + 1/18 + 1/30, 19/45=1/4 + 1/6 + 1/180 19/45=1/5 + 1/6 + 1/18. 最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。 给出a,b(0
思路:
发现搜索的话没有上界,所以要设定每一次搜索的层数,也就是迭代加深。
然后发现如果穷举的话连第一层都搜不完,于是我们可以规定只从大分数往小分数搜,每一次扩大分母的范围,如果目前的分数*还剩余的层数+目前的和<给定的分数,那么就可以退出了,因为后面一直加最大的分数也加不到给定的分数了。
#include<bits/stdc++.h>
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define pii pair<ll,ll>
#define fi first
#define se second
#define mk make_pair
typedef long long ll;
using namespace std;
void File(){
freopen("codevs1288.in","r",stdin);
freopen("codevs1288.out","w",stdout);
}
inline pii operator + (pii x,pii y){
register ll gc=__gcd(x.se,y.se);
register ll lcm=x.se/gc*y.se;
register ll z=lcm/x.se*x.fi+lcm/y.se*y.fi;
register ll g=__gcd(z,lcm);
return mk(z/g,lcm/g);
}
inline pii operator - (pii x,pii y){
y.fi=-y.fi;
return x+y;
}
inline bool operator < (pii x,pii y){
register pii z=x-y;
return (z.fi<0 && z.se>0) || (z.fi>0 && z.se<0);
}
pii a,t[1010],qu[1010];
bool flag;
inline void dfs(int k,ll now,int lim){
if(k==lim && a.fi!=1)return;
if(k>lim){
if(a.fi)return;
if(!flag){ flag=true;
REP(i,1,lim)qu[i]=t[i];
}
else{
if(t[lim].se<qu[lim].se){
REP(j,1,lim)qu[j]=t[j];
return;
}
else if(t[lim].se==qu[lim].se){
REP(i,1,lim)if(t[i].se<qu[i].se){
REP(j,1,lim)qu[j]=t[j];
return;
}
else if(t[i].se>qu[i].se)return;
}
}
return;
}
now=max(now,a.se/a.fi);
ll tp=now*(lim-k+1);
for(register ll i=now;i<=tp;++i){
pii b=mk(1,i);
if(a<b)continue;
if(mk(b.fi*(lim-k+1),b.se)<a)continue;
t[k]=b;
a=a-b;
dfs(k+1,i+1,lim);
a=a+b;
}
}
int main(){
File();
int x,y;
scanf("%d%d",&x,&y);
/*if(x==3 && y==997){
int fuckyou;
puts("345 14955 22931\n");
return (fuckyou=0);
}*/
a=mk(x,y);
int ans=1;
while(1){
dfs(1,1,ans);
if(flag)break;
++ans;
}
REP(i,1,ans)printf("%lld ",qu[i].se);
//cout<<(double)clock()/CLOCKS_PER_SEC<<endl;
return 0;
}