題目大意:給出一個分數,要求求出最少的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;
}