题目大意:给出一个分数,要求求出最少的x分之1的形式,如果个数相同,要求最小的数字最大。
考虑搜索,因为总个数不确定,使用IDDFS,每次确定一个长度,对于每一个位置从可以成立的最小值开始枚举。
对于最终情况:如果这次的a为1,并且b比前面的一次大,那么就是最终情况,这时如果这个长度没出现过,那么当前序列
作为答案,如果出现过,那么选择最大的最后一位作为答案。
对于搜索,每一次的新值的最小值一定要比当前的b/a大,这样1/i就比a/b大,同时也要比上一个选择i要大,因为我们选择的
答案是递增的。对于最大值,极限情况就是后续都选择i时,整体要比a/b大,所以i<(now-dep+1)*b/a。
如果最大值大于int要缩成int的极限值-1(玄学优化。。。),如果这个长度已经有过答案了,那么极限值要比目前答案的最小值
大,这样才有意义。传入下一层的就是a/b-1/i的对应分子和分母。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll a,b,ans[15],tmp[15],now,inf=2147483647;
ll gcd(ll x,ll y)
{
if(y==0)return x;
return gcd(y,x%y);
}
int flag;
void dfs(ll dep,ll na,ll nb)
{
if(dep>now)return;//这个地方也可以和下面的判断写在一起,当然了如果有最优答案早就结束了
if(na==1&&nb>tmp[dep-1])
{
tmp[dep]=nb;
if(!flag||tmp[dep]<ans[dep])
{
memcpy(ans,tmp,sizeof(tmp));
}
flag=1;return;
}
ll st=max(nb/na,tmp[dep-1]+1),ed=(now-dep+1)*nb/na;
if(ed>inf)ed=inf-1;
if(flag&&ed>=ans[now])ed=ans[now]-1;
for(ll i=st;i<=ed;i++)
{
tmp[dep]=i;
ll ty=gcd(na*i-nb,nb*i);
dfs(dep+1,(na*i-nb)/ty,nb*i/ty);
}
}
int main()
{
scanf("%lld%lld",&a,&b);
ll c=gcd(a,b);
a/=c,b/=c;
if(a==1)
{
printf("%lld\n",b);
return 0;
}
tmp[0]=1;
for(now=1;;now++)
{
dfs(1,a,b);
if(flag)
{
for(int i=1;i<=now;i++)
{
printf("%lld ",ans[i]);
}
return 0;
}
}
return 0;
}