斐波那契的纠结 [Tyvj 1532]

45 篇文章 0 订阅
2 篇文章 0 订阅

题目地址请点击——


斐波那契的纠结


Background

继上次Zyj成功地鬼了TB的机子之后,Zyj收到了各路神犇Orz性质的语言(会掉RP的)。
不过一天Zyj看见了这样一句话:“畸形就像斐波那契数列般绵延。”
看着这一句,Zyj灵感一现,一道新题就出来了!


Description

一天,Zyj懂得了Fibonacci数列,发现数列有以下规律:
F[1]=F[2]=1 F[N]=F[N1]+F[N2]
于是Zyj觉得很神奇,想知道任意两个Fibonacci数有没有大于 1 的公约数。
但是光在有限的范围内手算还不行,于是Zyj找到了你,希望你能帮忙编个程序算算。
任务:指定两个Fibonacci数的项数(也就是这两个数各是第几项),求出这两个数的最大公约数。
例如输入 3 6,输出 2 (因为 GCD(F[3],F[6])=2)。


Input

每个输入文件都有 10 组数据,每组数据格式如下:
只有一行:两个整数 A B(数据规模见【注释HINT】),表示要求公约数的两个数是 F[A] F[B]


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
保证最后输出的数字不超过 2641 (所以请用 64 位无符号整数
可能会有数据重复出现,因为这是随机数,且Zyj不想写判重,太麻烦-_-“,照常做即可。


Solution

首先 gcd(Fib(x),Fib(y))=Fib(gcd(x,y)) 证明请点击——

因为输出的数字不超过 2641 ,所以 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值