【题解】洛谷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 i b m , F i b n ) = F i b gcd ( m , n ) \gcd(Fib_m,Fib_n)=Fib_{\gcd(m,n)} ,于是就可以矩阵递推了。时间复杂度 O ( 2 3 log gcd ( m , n ) ) O\Big(2^3\log \gcd(m,n)\Big)

#include<cstdio>
#include<cstring>
const int mod=1e8;
int gcd(int n,int m){return m?gcd(m,n%m):n;}
int p,f[2]={0,1},a[2][2]={{0,1},{1,1}};
void mul()
{
	int c[2];memset(c,0,sizeof(c));
	for(int i=0;i<=1;i++)
	    for(int j=0;j<=1;j++)
	        c[i]=(c[i]+1ll*f[j]*a[j][i])%mod;
	memcpy(f,c,sizeof(c));
}
void mulself()
{
	int c[2][2];memset(c,0,sizeof(c));
	for(int i=0;i<2;i++)
	    for(int j=0;j<2;j++)
	        for(int k=0;k<2;k++)
	            c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j])%mod;
	memcpy(a,c,sizeof(c));
}
void qpow()
{
	for(;p;p>>=1)
	{
		if(p&1)mul();
		mulself();
	}
	printf("%d\n",f[0]);
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	p=gcd(n,m);
	qpow();
	return 0;
}

总结

这个性质很关键,然后矩阵那里也有点不太会写了。

猜你喜欢

转载自blog.csdn.net/qq_41958841/article/details/82800481
今日推荐