【题解】洛谷P1306斐波拉契公约数 矩阵快速幂

本文探讨Fibonacci数列中任意两项的最大公约数(GCD)的高效计算方法,通过矩阵递推利用斐波那契数列的特殊性质,在O(2^3logGCD(m,n))的时间复杂度下解决大数问题。

题目链接

题目描述

对于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)} gcd(Fibm,Fibn)=Fibgcd(m,n),于是就可以矩阵递推了。时间复杂度 O ( 2 3 log ⁡ gcd ⁡ ( m , n ) ) O\Big(2^3\log \gcd(m,n)\Big) O(23loggcd(m,n))

#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;
}

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值