1 /* 2 对于一个n,它在新的数列里最多是第45项,因此可以遍历查找 3 a 4 b 5 a+b 6 a+2*b 7 2*a+3*b 8 3*a+5*b 9 有上面的规律可知 G[i]=f[i-2]*a+f[i-1]*b 10 我们要求的就是 a,b。 11 */ 12 #include <iostream> 13 #include <cstdio> 14 #include <cstring> 15 #include <algorithm> 16 #include <set> 17 #include <map> 18 #include <vector> 19 #include <cmath> 20 using namespace std; 21 typedef long long ll; 22 const int inf=0x3f3f3f3f; 23 int t; 24 ll f[56]; 25 void init() 26 { 27 f[1]=1,f[2]=1; 28 for(int i=3;i<=48;i++) 29 { 30 f[i]=f[i-2]+f[i-1]; 31 } 32 } 33 ll egcd(ll a,ll b,ll &x,ll &y) 34 { 35 ll d=a; 36 if(b==0){ 37 x=1; 38 y=0; 39 } 40 else{ 41 d=egcd(b,a%b,y,x); 42 y-=(a/b)*x; 43 } 44 return d; 45 } 46 //egcd求出的是a,b的最大公约数 47 int main() 48 { 49 scanf("%d",&t); 50 init(); 51 while(t--) 52 { ll n; 53 scanf("%lld",&n); 54 ll l=1,r=n; 55 for(int i=3;i<=45;i++)//45就已经大于10^9了 56 { 57 if(f[i]>n) break; 58 //G[i]=f[i-2]*a+f[i-1]*b,G[i]最小为f[i] 59 //G[i]等于n吗 60 ll x,y; 61 ll tmp=egcd(f[i-2],f[i-1],x,y); 62 if(n%tmp!=0) continue; 63 x*=n,y*=n;////a*x+b*y=1(egcd),是1 64 ll ans=(y-x)/f[i]; 65 x+=ans*f[i-1]; 66 y-=ans*f[i-2]; 67 //数学公式可推出:x,y都为(x*f[i-2]+y*f[i-1])/f[i] 68 if(x>y) { 69 x-=f[i-1];//多加了,减回去 70 y+=f[i-2]; 71 } 72 //上面的操作是为了让a,b,更接近 73 74 if(x<=0||y<=0) continue; 75 if(r>y) {//r要小 76 r=y; 77 l=x; 78 } 79 else if(r==y&&l>x){//r一样大时。l要小 80 l=x; 81 } 82 } 83 printf("%lld %lld\n",l,r); 84 } 85 return 0; 86 }
Benelux Algorithm Programming Contest 2014 Final Interesting Integers
猜你喜欢
转载自www.cnblogs.com/tingtin/p/9291705.html
今日推荐
周排行