例4:求斐波那契数列前n项的和【矩阵乘法】【快速幂】【斐波那契数列】

题目

数列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的前n项和s[n]的快速求法(不考虑高精度).


思路

仿照之前的思路,
考虑1×3的矩阵 ∣ f [ n − 1 ] f [ n − 2 ] s [ n − 2 ] ∣ \begin{vmatrix}f[n-1]&f[n-2]&s[n-2]\end{vmatrix} f[n1]f[n2]s[n2]
我们希望通过乘以一个3×3的矩阵A,得到1×3的矩阵:
∣ f [ n ] f [ n − 1 ] s [ n − 1 ] ∣ \begin{vmatrix}f[n]&f[n-1]&s[n-1]\end{vmatrix} f[n]f[n1]s[n1]   =   ~=~  =  ∣ f [ n − 1 ] + f [ n − 2 ] f [ n − 1 ] s [ n − 2 ] + f [ n − 1 ] ∣ \begin{vmatrix}f[n-1]+f[n-2]&f[n-1]&s[n-2]+f[n-1]\end{vmatrix} f[n1]+f[n2]f[n1]s[n2]+f[n1]
容易得到这个3×3的转移矩阵是:
∣ 1 1 1 1 0 0 0 0 1 ∣ \begin{vmatrix}1&1&1\\1&0&0\\0&0&1\end{vmatrix} 110100101

C o d e Code Code

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const long long mod=1000000007;
long long n,a[4][4],ans[4][4];
long long fd[4][4];
void jzcf(int m)
{
	long long c[4][4];
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    c[i][j]=0;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	  for(int k=1; k<=m; k++)
	     c[i][j]=(c[i][j]+(a[i][k]*ans[k][j])%mod)%mod;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    ans[i][j]=c[i][j];
}
void jzcf2(int m)
{
	long long c[4][4];
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    c[i][j]=0;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	  for(int k=1; k<=m; k++)
	     c[i][j]=(c[i][j]+(a[i][k]*a[k][j])%mod)%mod;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    a[i][j]=c[i][j];
}
void jzcf3()
{
	long long c[4][4];
	for(int i=1; i<=3; i++)
	 for(int j=1; j<=3; j++)
	    c[i][j]=0;
	for(int i=1; i<=1; i++)
	 for(int j=1; j<=3; j++)
	  for(int k=1; k<=3; k++)
	     c[i][j]=(c[i][j]+(fd[i][k]*ans[k][j])%mod)%mod;
	for(int i=1; i<=1; i++)
	 for(int j=1; j<=3; j++)
	    fd[i][j]=c[i][j];
}
void ksm(long long k)
{
	for(int i=1; i<=3; i++)
	   ans[i][i]=1;
	while(k!=0)
	 {
	 	if(k&1)
	 	  jzcf(3);
	 	jzcf2(3);
	 	k>>=1;
	 }
}
int main()
{
	cin>>n;
	if(n==1)
	 {
	 	cout<<1;
	 	return 0;
	 }
	a[1][1]=1,a[1][2]=1,a[1][3]=1;
	a[2][1]=1,a[2][2]=0,a[2][3]=0;
	a[3][1]=0,a[3][2]=0,a[3][3]=1;
	fd[1][1]=1,fd[1][2]=1,fd[1][3]=1;
	ksm(n-1);
	jzcf3();
    cout<<fd[1][3];
	return 0;
}
//矩阵快速幂里面的k是int,但是要用long long,不然会爆,n都开了long long了。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值