HDOJ 题目4549 M斐波那契数列(数学,矩阵快速幂,费马小定理)

本文介绍了一种特殊的斐波那契数列——M斐波那契数列的计算方法,通过使用矩阵快速幂和快速幂算法,有效地解决了大数值下数列计算的问题,并提供了AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

M斐波那契数列

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1386    Accepted Submission(s): 396


Problem Description
M斐波那契数列F[n]是一种整数数列,它的定义如下:

F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )

现在给出a, b, n,你能求出F[n]的值吗?
 

Input
输入包含多组测试数据;
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
 

Output
对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。
 

Sample Input
  
0 1 0 6 10 2
 

Sample Output
  
0 60
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   4959  4958  4957  4956  4955 
 

思路:

1. 首先得出封闭形式:

F[n]=a  (n=0)

F[n]=a^Fib[n-1]*b^Fib[n]  (n>0)

2. 发现1000000007是质数,遂用费马小定理,得

F[n]%m=a^(Fib[n-1]%(m-1))*b^(Fib[n]%(m-1))%m

3. f[n]%(m-1)的计算用矩阵快速幂

4. a^x的计算用快速幂

我的ac代码

说实话那个p矩阵为毛那么写,我还是真的不知道,求路过的大神帮一把

#include<stdio.h>
#include<string.h>
#include<math.h>
#define mod 1000000007
struct s
{
	__int64 mp[2][2];
};
struct s p={
	1,1,
	1,0,
};
struct s I={
	1,0,
	0,1,
};
struct s muti(struct s a,struct s b)
{
	struct s c;
	int i,j,k;
	memset(c.mp,0,sizeof(c.mp));
	for(i=0;i<2;i++)
		for(j=0;j<2;j++)
		{
			//c.mp[i][j]=0;
			for(k=0;k<2;k++)
			{
				c.mp[i][j]+=(a.mp[i][k]*b.mp[k][j])%(mod-1);
				
			}c.mp[i][j]%=(mod-1);
		}
	return c;
}
struct s mutip(__int64 n)
{
	struct s tp=p,ti=I;
	//printf("%I64d %I64d %I64d\n",ti.mp[1][1],ti.mp[1][0],n);
	while(n)
	{
		/*if(n&1)//这种快速幂写法也可以
		{
			ti=muti(ti,tp);
			n--;
		}
		else
		{
			tp=muti(tp,tp);
			n/=2;
		}*/
	//	printf("%I64d %I64d %I64d\n",ti.mp[1][1],ti.mp[1][0],n);
		if(n&1)
		{
			ti=muti(ti,tp);
			//printf("%I64d %I64d %I64d\n",ti.mp[1][1],ti.mp[1][0],n);
		}
		tp=muti(tp,tp);
		n>>=1;
	}
	return ti;
}
__int64 qpow(__int64 a,__int64 b)
{
	__int64 s=1;
	while(b)
	{
		if(b&1)
			s=s*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return s;
}
int main()
{
	__int64 a,b,n;
	while(scanf("%I64d%I64d%I64d",&a,&b,&n)!=EOF)
	{
		struct s pi=mutip(n);
		printf("%I64d\n",(qpow(a,pi.mp[1][1])*qpow(b,pi.mp[1][0]))%mod);
		//printf("%I64d %I64d\n",pi.mp[1][1],pi.mp[1][0]);
	}
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值