P1306 斐波那契公约数(矩阵快速幂)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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]);
}

猜你喜欢

转载自blog.csdn.net/qq872425710/article/details/82587771
今日推荐