版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq872425710/article/details/82587771
题目大意:
对于Fibonacci数列:1,1,2,3,5,8,13……大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?
思路:
这题有点好玩,首先他是一个结论题,知道结论很好做不知道结论就推一推把,思考一段时间可以发现gcd(f[n],f[m])==f[gcd(n,m)];然后矩阵快速幂求答案就好了。这里主要是结论的证明和如何想到。想到还是比较简单的,因为斐波拉契数列后面越来越大,所以快速幂求出来f[n],f[m],再gcd是不可能的,考虑把他优化成一个f,然后又要满足gcd的性质,就可以找出规律了,然后想证明。我们可以把f[m]用f[n]和f[n+1]表示出来
gcd(f[n],f[n]*a+f[n+1]*b)==gcd(f[n],f[n+1]*b),因为f[n]和f[n+1]一定是互质的,gcd(f[n],f[n+1]*b)==gcd(f[n],b);b又等于f[m-n]所以gcd(f[n],b)==gcd(f[n],f[n-m]),然后一直减gcd(f[n],f[m-n])==gcd(f[n],f[m%n]),可以看成在用下标求gcd所以gcd(f[n],f[m])==f[gcd(n,m)];
程序:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#define LL long long
#define mo 100000000
#define N 2
using namespace std;
int g[N][N],f[N][N],c[N][N],n,m;
int gcd(int x,int y){
if (y==0) return x;
return gcd(y,x%y);
}
void cheng(int a[N][N],int b[N][N],int x){
for (int i=0;i<2;i++)
for (int j=0;j<2;j++){
c[i][j]=0;
for (int k=0;k<2;k++)
c[i][j]=(c[i][j]+(LL)a[i][k]*b[k][j]%mo)%mo;
}
if (x==1) {
for (int i=0;i<2;i++)
for (int j=0;j<2;j++)
g[i][j]=c[i][j];
} else{
for (int i=0;i<2;i++)
for (int j=0;j<2;j++)
f[i][j]=c[i][j];
}
}
void mul(int n){
while (n){
if (n&1) cheng(g,f,1);
cheng(f,f,0);
n>>=1;
}
}
int main(){
scanf("%d%d",&n,&m);
n=gcd(n,m);
f[0][0]=1; f[0][1]=1; f[1][0]=1;
g[0][0]=1; g[1][1]=1;
mul(n);
printf("%d",g[0][1]);
}