斐波那契的纠结
Background
继上次Zyj成功地鬼了TB的机子之后,Zyj收到了各路神犇Orz性质的语言(会掉RP的)。
不过一天Zyj看见了这样一句话:“畸形就像斐波那契数列般绵延。”
看着这一句,Zyj灵感一现,一道新题就出来了!
Description
一天,Zyj懂得了Fibonacci数列,发现数列有以下规律:
F[1]=F[2]=1
;
F[N]=F[N−1]+F[N−2]
;
于是Zyj觉得很神奇,想知道任意两个Fibonacci数有没有大于
1
的公约数。
但是光在有限的范围内手算还不行,于是Zyj找到了你,希望你能帮忙编个程序算算。
任务:指定两个Fibonacci数的项数(也就是这两个数各是第几项),求出这两个数的最大公约数。
例如输入
Input
每个输入文件都有
10
组数据,每组数据格式如下:
只有一行:两个整数
A
和
Output
对于每组数据,输出相应的 GCD(F[A],F[B]) 即可。(也就是说有 10 行输出。)
Sample Input 1
30 15
14 28
12 24
17 17
30 6
24 24
20 10
24 12
29 29
9 18
Sample Output 1
610
377
144
1597
8
46368
55
144
514229
34
Sample Input 2
19 19
24 8
10 20
28 28
30 30
11 22
6 24
24 16
15 15
22 11
Sample Output 2
4181
21
55
317811
832040
89
8
21
610
89
Hint
50%
的数据:
0<A,B<32
100%
的数据:
0<A,B<100002
保证最后输出的数字不超过
264−1
(所以请用
64
位无符号整数)
可能会有数据重复出现,因为这是随机数,且Zyj不想写判重,太麻烦-_-“,照常做即可。
Solution
首先 gcd(Fib(x),Fib(y))=Fib(gcd(x,y)) ,证明请点击——
因为输出的数字不超过
264−1
,所以
gcd(x,y)
应该不超过
100
,所以
O(n)
求即可。
为了练手,我打的是
O(logn)
的。
Code
#include <iostream>
#include <cstdio>
#define LL unsigned long long
using namespace std;
LL a,b,g,pre,post;
LL gcd(LL x,LL y){
return y==0?x:gcd(y,x%y);
}
void fib(LL x){
if(x==1){pre=1;post=0;return;}
if(x==2){pre=post=1;return;}
if(x&1){
fib(x-1);
pre+=post;
post=pre-post;
return;
}
fib(x/2);
LL fp=pre,fpo=post;
pre=fp*fp+2*fpo*fp;
post=fp*fp+fpo*fpo;
}
int main(){
while(scanf("%llu%llu",&a,&b)!=EOF){
g=gcd(a,b);
fib(g);
printf("%llu\n",pre);
}
return 0;
}