https://www.luogu.org/problem/P1306
题目描述
对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少?
Update:加入了一组数据。
输入格式
两个正整数n和m。(n,m<=10^9)
注意:数据很大
输出格式
Fn和Fm的最大公约数。
由于看了大数字就头晕,所以只要输出最后的8位数字就可以了。
输入输出样例
输入 #1复制
4 7
输出 #1复制
1
说明/提示
用递归&递推会超时
用通项公式也会超时
首先,有个神奇的公式:gcd(F[m],F[n])=F[gcd(m,n)];设q=gcd(m,n),那么求Fn和Fm的最大公约数,就相当于求F[q];
然后求斐波纳契数列的第q项,还要比用递归和通项公式更快,就要借助矩阵快速幂了;构造初始矩阵[F[2],F[1]],既[1,1];
构造中间矩阵m[1][1]=1;m[1][2]=1;m[2][1]=1;m[2][2]=0; 显然初始矩阵*中间矩阵=[2,1];初始矩阵*(中间矩阵)^2=[3,2];
那么初始矩阵*(中间矩阵)^x=[F[x+2],F[x+1]];
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e8;
struct Martrix{
ll m[3][3];
};
Martrix mul(Martrix a,Martrix b)
{
Martrix c;
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
c.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++)
{
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
c.m[i][j]%=mod;
}
return c;
}
Martrix pow(Martrix a,ll b)
{
Martrix ans,base=a;
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
ans.m[i][j]=0;
for(int i=1;i<=2;i++)
ans.m[i][i]=1;
while(b)
{
if(b%2==1)
ans=mul(ans,base);
base=mul(base,base);
b/=2;
}
return ans;
}
Martrix fa,mu,Q;
int main()
{
ll m,n;
cin>>m>>n;
ll q=__gcd(m,n);
fa.m[1][1]=1;
fa.m[1][2]=1;
mu.m[1][1]=1;
mu.m[1][2]=1;
mu.m[2][1]=1;
mu.m[2][2]=0;
Q=pow(mu,q-2);
Q=mul(fa,Q);
cout<<Q.m[1][1];
return 0;
}