题目
洛谷 https://www.luogu.org/problemnew/show/P1306
对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?
输入输出格式
输入格式:
两个正整数n和m。(n,m<=10^9)
注意:数据很大
输出格式:
Fn和Fm的最大公约数。
由于看了大数字就头晕,所以只要输出最后的8位数字就可以了。(%100000000)
分析
对于 gcd(F[n],F[m]) 假令 n<m F[n]=x ,F[n+1]=y;
F[n+2]=x+y =F[1]*x+F[2]*y
F[n+3]=x+2*y =F[2]*x+F[3]*y
F[n+4]=2*x+3*y =F[3]*x+F[4]*y
...
F[m]=F[m-n-1]*x+F[m-n]*y 又F[n]=x;
则Gcd(F[n],F[m])=Gcd(F[n],F[n+1]*F[m-n])
又F[n+1]-F[n]=F[n-1]
且Gcd(F[n+1],F[n]) =Gcd(F[n],F[n+1]-F[n]) (辗转相减法,辗转相除的变式)
=Gcd(F[n],F[n-1])
=Gcd(F[n-1],F[n-2]) (同理)
=Gcd(F[3],F[2])=1;
故Gcd(F[n],F[m])=Gcd(F[n],F[n+1]*F[m-n])=Gcd(F[n],F[m-n])
=Gcd(F[m-n],F[m-2*n]) (同理)
.....
=Gcd(F[Gcd(n,m)],F[Gcd(n,m)]) (辗转相减法的变形)
得到Gcd(F[n],F[m])=F[Gcd(n,m)];
对于F[Gcd(n,m)]的求解,运用矩阵快速幂优化(矩阵乘幂优化线性递推式)
代码
1 #include<queue>
2 #include<cstdio>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 using namespace std;
7 typedef long long ll;
8 const int mod=100000000;
9 int N,M;
10 struct data{
11 int r,c;
12 ll a[3][3];
13 data(){
14 memset(a,0,sizeof(a));
15 }
16 friend data operator*(data a,data b){
17 data c;
18 c.r=a.r;c.c=b.c;
19 for(int i=1;i<=a.r;i++)
20 for(int k=1;k<=a.c;k++)
21 for(int j=1;j<=b.c;j++)
22 (c.a[i][j]+=a.a[i][k]*b.a[k][j])%=mod;
23 return c;
24 }
25 };
26 int Gcd(int x,int y){
27 if(y==0) return x;
28 return Gcd(y,x%y);
29 }
30 ll Fast(int t){
31 data a,b,c;
32 a.r=2,a.c=2;
33 a.a[1][1]=1,a.a[1][2]=1,a.a[2][1]=1;
34 b.r=2,b.c=1;
35 b.a[1][1]=b.a[2][1]=1;
36 while(t){
37 if(t&1) b=a*b;
38 a=a*a;
39 t=t>>1;
40 }
41 return b.a[1][1];
42 }
43 int main(){
44 scanf("%d%d",&N,&M);
45 int t=Gcd(N,M);
46 if(t<=2) cout<<1<<endl;
47 else cout<<Fast(t-2);
48 return 0;
49 }