加强版斐波那契数列(矩阵快速幂)

本文介绍如何使用矩阵快速幂解决一个加强版斐波那契数列问题,给出具体的C++代码实现,并详细解释了如何从普通斐波那契数列递推式转换到适用于快速幂的矩阵形式。

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

关于快速幂的讲解可以参见我的上一篇博客《快速幂》

题目链接:又见斐波那契

题目描述 

这是一个加强版的斐波那契数列。
给定递推式
求F(n)的值,由于这个值可能太大,请对10 9+7取模。

输入描述:

第一行是一个整数T(1 ≤ T ≤ 1000),表示样例的个数。
以后每个样例一行,是一个整数n(1 ≤ n ≤ 1018)。

输出描述:

每个样例输出一行,一个整数,表示F(n) mod 1000000007。
示例1

输入

4
1
2
3
100

输出

1
16
57
558616258

这个相比普通的斐波那契数列多了后面四项,看一眼数据范围,使用普通的o(n)的算法肯定会超时,

因此这里需要使用矩阵快速幂(斐波那契数列的项数n一旦过大,就要考虑快速幂,普通算法时间空间都开销太大)。

使用矩阵快速幂的一个关键问题就是矩阵递推式。

参考普通快速幂那一片博客最后面的那个扩展式,就可以得到下面这个递推式了:


然后通过计算等价替换可得出该矩阵A:


下面只需要把普通斐波那契数列的构造由2*2的矩阵换为6*6的即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector> 
#include <cstring>
 
using namespace std;

typedef long long ll;

// 用二维vector来表示矩阵 
typedef vector<ll> vec;
typedef vector<vec> mat;

// 模 
const int M = 1000000007;

// 计算 A*B
mat mul(mat& A, mat& B) {
	mat C(A.size(), vec(B[0].size()));
	for ( int i = 0 ; i < A.size() ; ++ i ) {
		for ( int k = 0 ; k < B.size() ; ++ k ) {
			for ( int j = 0 ; j < B[0].size() ; ++ j ) {
				C[i][j] = (C[i][j]+A[i][k]*B[k][j]%M)%M;
			}
		}
	}
	return C;
}

// 计算 A^B
mat pow(mat A, ll n) {
	mat B(A.size(), vec(A.size()));
	for ( int i = 0 ; i < A.size() ; ++ i ) {
		B[i][i] = 1;
	}
	while ( n > 0 ) {
		if ( n & 1 ) B = mul(B, A);
		A = mul(A, A);
		n >>= 1;
	}
	return B;
} 

int main()
{
    int T;
    scanf( "%d", &T );
    ll n;
    mat A(6, vec(6));
    while ( T -- ) {
        scanf( "%lld", &n );
        if ( n == 0 ) { puts( "0" ); continue; }
        if ( n == 1 ) { puts( "1" ); continue; }
        for ( int i = 0 ; i < 6 ; ++ i ) {
        	for ( int j = 0 ; j < 6 ; ++ j ) {
        		A[i][j] = 0;
        	}
        }
        A[0][0] = 1; A[0][1] = 1; A[0][2] = 1; A[0][3] = 4; A[0][4] = 6; A[0][5] = 4;
        A[1][0] = 1;
        A[2][2] = 1; A[2][3] = 3; A[2][4] = 3; A[2][5] = 1;
        A[3][3] = 1; A[3][4] = 2; A[3][5] = 1;
        A[4][4] = 1; A[4][5] = 1;
        A[5][5] = 1;
        A = pow(A, n-1);
        ll ans = 0;
        for ( int i = 0 ; i < 6 ; ++ i ) {
        	if ( i == 1 ) continue;
			ans = (ans+A[0][i])%M;
        }
		printf( "%lld\n", ans );
    }  
    return 0;
}




### C++ 实现斐波那契数列矩阵快速幂 为了高效计算大项的斐波那契数值,可以采用矩阵快速幂算法。该方法利用了斐波那契数列相邻两项之间的线性关系: \[ \begin{bmatrix} F(n) \\ F(n-1) \end{bmatrix} = M^{n-1} * \begin{bmatrix} 1 \\ 0 \end{bmatrix},\quad where\;M=\begin{bmatrix} 1 & 1\\ 1& 0 \end{bmatrix}\] 通过这种方可以在 \(O(\log n)\) 时间复杂度内完成计算。 下面是一个完整的 C++ 程序来展示如何实现这一过程: ```cpp #include <iostream> using namespace std; struct Matrix { long long mat[2][2]; }; Matrix multiply(const Matrix& A, const Matrix& B){ Matrix result; for(int i=0;i<2;++i) for(int j=0;j<2;++j){ result.mat[i][j]=0; for(int k=0;k<2;++k) result.mat[i][j]+=(A.mat[i][k]*B.mat[k][j])%1000000007; result.mat[i][j]%=1000000007; } return result; } // 快速幂函数用于加速矩阵乘法运算 Matrix power(Matrix base,long exp){ Matrix res={{1,0},{0,1}};//单位阵初始化 while(exp>0){ if(exp&1)//如果exp为奇数,则多做一次乘法操作 res=multiply(res,base); base=multiply(base,base);//平方基数 exp>>=1;//右移一位相当于除以二 } return res; } long fibonacci(long N){ if(N==0)return 0; Matrix initial{{1,1},{1,0}}; Matrix powered_matrix=power(initial,N-1); return powered_matrix.mat[0][0]%1000000007; } ``` 此程序定义了一个 `multiply` 函数来进行两个矩阵相乘的操作,并且实现了 `power` 方法用来执行高效的矩阵指数运算。最后,在 `fibonacci` 函数里调用了这些辅助功能并返回第N个斐波那契数的结果[^1]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值