https://www.luogu.org/problem/show?pid=1306#sub
证:gcd(f(m),f(n))=f(gcd(m,n))
引理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]
证明:
F[n+m] =F[n+m-1]+F[n+m-2]
=2*F[n+m-2]+F[n+m-3]
=……
设 F[n+m]
=a[x]*F[n+m-x]+b[x]*F[n+m-x-1];
=a[x](F[n+m-x-1]+F[n+m-x-2])+b[x](F[n+m-x-1);
=(a[x]+b[x])*F[n+m+x-1]+a[x]*F[n+m+x-2];
当x=1时有 a[1]=F[2]; b[1]=F[1];
当x=2时有 a[2]=F[2]+F[1]=F[3]; b[2]=a[1]=F[2];
当x=k+1时有 a[k+1]=a[k]+b[k]=F[k+1]+F[k]=F[k+2] b[k+1]=a[k]=F[k+1];
所以当x=n时有
F[n+m]=a[n]F[m]+b[n]F[m-1];
=F[n+1]F[m]+F[n]F[m-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]);
于是显然有:Gcd(F[n],F[m])=F[Gcd(n,m)];
题解里抄的哈哈
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
struct jv{
Ll a[3][3];
jv(){memset(a,0,sizeof a);}
};
int n,m,mo=1e8;
int gcd (int x,int y){return !y?x:gcd(y,x%y);}
jv X(jv a,jv b){
jv c;
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int k=1;k<=2;k++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mo;
return c;
}
jv ksm(jv a,int k){
jv ans=a;
for(k--;k;k>>=1,a=X(a,a))
if(k&1)ans=X(ans,a);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
n=gcd(n,m);
if(n<3){printf("1");return 0;}
jv a;
a.a[1][1]=a.a[1][2]=a.a[2][1]=1;
a=ksm(a,n-2);
printf("%lld",(a.a[1][1]+a.a[1][2])%mo);
}