对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?
结论:gcd (F[n] , F[m]) = F [gcd ( n , m )]
引理1:gcd ( F[n+1] , F[n] ) = 1
gcd(F[n+1],F[n])
=gcd(F[n+1]-F[n],F[n])
=gcd(F[n],F[n-1])
=gcd(F[2],F[1])
=1
引理2:F[m+n] = F[m-1] * F[n] + F[m] * F[n+1]
太长了
引理3:gcd ( F[n+m] , F[n] ) = gcd ( F[n] , F[m] )
gcd(F[n+m],F[n])
=gcd(F[n+1]F[m]+F[n]F[m-1],F[n])
=gcd(F[n+1]F[m],F[n])
=gcd(F[n+1],F[n])*gcd(F[m],F[n])
=gcd(F[m],F[n]);
由辗转相除法则原结论得证
所以只用求f[gcd(n,m)]即可,由于n,m太大,要用矩阵快速幂
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define ll long long using namespace std; const int mod=1e8; inline int read(){ int x=0,k=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return k*x; } struct matrix{ ll m[3][3]; }ans,res; matrix mul(matrix a,matrix b){ matrix tmp; for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) tmp.m[i][j]=0; for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) for(int k=1;k<=2;k++) tmp.m[i][j]=(tmp.m[i][j]+a.m[i][k]%mod*b.m[k][j]%mod)%mod; return tmp; } void poww(ll x){ while(x){ if(x&1) ans=mul(ans,res); res=mul(res,res); x>>=1; } } ll gcd(ll x,ll y){ return y?gcd(y,x%y):x; } int main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); ll n,m; n=read();m=read(); n=gcd(n,m); ans.m[1][1]=1;ans.m[1][2]=1; res.m[1][1]=1;res.m[2][1]=1;res.m[1][2]=1; if(n==1||n==2){ cout<<1; return 0; } poww(n-2); cout<<ans.m[1][1]%mod; return 0; }