Benelux Algorithm Programming Contest 2014 Final Interesting Integers

 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 }

猜你喜欢

转载自www.cnblogs.com/tingtin/p/9291705.html