矩阵快速幂 -codevs斐波拉契数列2

1732 Fibonacci数列 2

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
在“1250 Fibonacci数列”中,我们求出了第n个Fibonacci数列的值。但是1250中,n<=10 9 。现在,你的任务仍然是求出第n个Fibonacci数列的值,但是注意:n为整数,且1 <= n <= 100000000000000
输入描述 Input Description

输入有多组数据,每组数据占一行,为一个整数n(1 <= n <= 100000000000000)

输出描述 Output Description

输出若干行。每行输出第(对应的输入的)n个Fibonacci数(考虑到数会很大,mod 1000000007)

样例输入 Sample Input

3
4
5

 

样例输出 Sample Output

2
3
5

 

数据范围及提示 Data Size & Hint

1 <= n <= 100000000000000



数据大了会超时?开玩笑,2^3 log n这么小的数量级,秒秒钟跑完,重载运算符跑一下就好了,思路和斐波拉契1一样。

构造一个T矩阵,自乘n-2次,再和初始矩阵相乘,取mat[1][1]就好了。

注意因为数据大了,有可能乘起来爆int  ,因为两个数都很接近mod的话,乘起来是爆int的,改用long long


#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const LL maxn=5;
LL n;
const LL M=1000000007;
struct Mat
{
	LL mat[maxn][maxn];
};
Mat operator*(Mat a,Mat b)
{
	Mat c;
	memset(c.mat,0,sizeof(c.mat));
	for(LL k=1;k<=2;k++)
	{
		for(LL i=1;i<=2;i++)
		{
			for(LL j=1;j<=2;j++)
			{
				c.mat[i][j]+=(a.mat[i][k]%M*b.mat[k][j]%M);
				c.mat[i][j]%=M;
			}
		}
	}
	return c;
}
Mat operator ^(Mat a,LL k)
{
	Mat c;
	memset(c.mat,0,sizeof(c.mat));
	for(LL i=1;i<=2;i++)
	{
		for(LL j=1;j<=2;j++)c.mat[i][j]=(i==j);
	}
	for(;k;k>>=1)
	{
		if(k&1)c=c*a;
		a=a*a;
	}
	return c;
}
int main()
{
	freopen("2.out","w",stdout);
	while(scanf("%lld",&n)!=EOF)
	{
		if(n<3)printf("1\n");
		else
		{
			Mat f,g;
			memset(f.mat,0,sizeof(f.mat));
			f.mat[1][1]=f.mat[1][2]=f.mat[2][1]=1;
			g=f^(n-2);
			f.mat[1][2]=0;
			g=g*f;
			printf("%lld\n",g.mat[1][1]);
		}		
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值