思路:
1.Stern-Brocot樹可以構成所有有理數。
2.對於每次在m1/n1,m2/n2中插入(m1+m2)/(n1+n2)構成下一排。
3.Stern-Brocot樹構成的所有分數均爲最簡分數,即gcd(m,n)==1。
其中,第N排的真分數部分爲N階Farey序,滿足對於連續的分數m1/n1,m2/n2,必有m1/n1<m2/n2。
由此,取該數的小數部分,二分答案即可。
注意:此題卡long double。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
long double lt;
int ansl,ansr;
void solve(int l1,int r1,int l2,int r2)
{
if(l1==l2&&r1==r2) return ;
if(fabs((long double)l1/r1-lt)<fabs((long double)ansl/ansr-lt))
{
ansl=l1;
ansr=r1;
}
if(fabs((long double)l2/r2-lt)<fabs((long double)ansl/ansr-lt))
{
ansl=l2;
ansr=r2;
}
int ml=(l1+l2);
int mr=(r1+r2);
if(mr>100000) return ;
if((long double)ml/mr<lt) solve(ml,mr,l2,r2);
else solve(l1,r1,ml,mr);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int flag=0,k;
scanf("%d",&k);
ansl=ansr=1;
long double tmp=pow((long double)k,(long double)2.0/3.0);
lt=tmp-(int)floor(tmp);
solve(0,1,1,1);
printf("%d/%d\n",(int)floor(tmp)*ansr+ansl,ansr);
}
return 0;
}