矩阵快速幂——斐波那契数列进一步优化
快速幂优化矩阵幂、乘法
对于一般的矩阵计算有 \(A_{m,n}*B_{n,p}=C_{m,p}\),其中作为乘积因子的两个矩阵必须满足前因子列数与后因子行数相同
积的行数等于前因子的行数,列数等于后因子的列数 ,任意的 \(c_{i,j}\) 可由定义的计算得出 \(c_{i,j}=\sum_{k=1}^{n} a_{i,k}*b_{k,j}\)
幂运算
可以通过快速幂优化矩阵的幂乘法,即计算 \(A^k\)
struct matrix { long long mtx[N][N]; matrix() { memset(mtx, 0, sizeof mtx); } };//定义矩阵结构体
其中 matrix() { memset(mtx, 0, sizeof mtx); }
可以在每次定义矩阵时,都对矩阵成员进行初始化为 \(0\)
matrix operator*(matrix& x, matrix& y) { matrix t; for (int i = 1; i <= n; i++)//行 for (int j = 1; j <= n; j++)//列 for (int k = 1; k <= n; k++)//当前矩阵的内数 t.mtx[i][j] += x.mtx[i][k] * y.mtx[k][j]; return t; }
重载矩阵的乘法运算符,通过普遍公式计算给出
matrix matrix_quick_pow(matrix a, long long k) {//矩阵类型的快速幂计算函数 matrix res; for (int i = 1; i <= n; i++) res.mtx[i][i] = 1; while (k) { if (k & 1) res = res * a; a = a * a; k >>= 1; } return res; }
定义 res
时,需要对其进行初始化为一个单位矩阵作为乘积的基
加速斐波那契数列
对于斐波那契数列有以下通项公式 \(F_n=F_{n-1}+F_{n-2}\)
设存在矩阵 \(A\) 使得
\[\left[\begin{matrix}F_n&F_{n-1}\end{matrix}\right]
=
\left[\begin{matrix}F_{n-1}&F_{n-2}\end{matrix}\right]
*
A
\quad
A
=
\left[\begin{matrix}a&b\\c&d\end{matrix}\right]
\]
结合通项公式,合并矩阵后等式变化为
\[\left[\begin{matrix}F_n&F_{n-1}\end{matrix}\right]
=
\left[\begin{matrix}F_{n-1}&F_{n-2}\end{matrix}\right]
*
\left[\begin{matrix}1&1\\1&0\end{matrix}\right]
\]
因为\(F_1=F_2=1\) 已知,递推到底层有
\[\left[\begin{matrix}F_n&F_{n-1}\end{matrix}\right]
=
\left[\begin{matrix}F_{2}&F_{1}\end{matrix}\right]
*
\left[\begin{matrix}1&1\\1&0\end{matrix}\right]^{n-2}
\]
最终可化简为
\[\begin{cases}
\left[\begin{matrix}F_n&F_{n-1}\\F_{n-1}&F_{n-2}\end{matrix}\right]
=
\left[\begin{matrix}1&1\\1&0\end{matrix}\right]^{n-1}&(n>2)
\\\\F_n=1&(n=1,2)
\end{cases}
\]
此时可以发现,计算斐波那契数列的各项值就只需要计算矩阵的 \(n\) 次方,结合上面的矩阵快速幂,可以做到在 \(O(\log n)\) 的时间复杂度内计算出第 \(n\) 项
matrix a; init(a); void init(matrix &a) { a.mxt[1][1] = 1; a.mxt[1][2] = 1; a.mxt[2][1] = 1; }
初始化斐波那契矩阵
auto ans = matrix_quick_pow(a, n - 1); cout << ans.mxt[1][1] << endl;
根据公式,最后输出第一行第一列的元素即可
完整代码:
#include <iostream> #include <cstring> using namespace std; const long long mod = 1e9 + 7; long long n; struct matrix { long long mxt[3][3]; matrix() { memset(mxt, 0, sizeof mxt); }; }; matrix operator*(matrix& x, matrix& y) { matrix t; for (int i = 1; i <= 2; i++) for (int j = 1; j <= 2; j++) for (int k = 1; k <= 2; k++) t.mxt[i][j] = (t.mxt[i][j] + x.mxt[i][k] * y.mxt[k][j]) % mod; return t; } void init(matrix &a) { a.mxt[1][1] = 1; a.mxt[1][2] = 1; a.mxt[2][1] = 1; } matrix matrix_quick_pow(matrix a, long long n) { matrix res; for (int i = 0; i <= 2; i++) res.mxt[i][i] = 1; while (n) { if (n & 1) res = res * a; a = a * a; n >>= 1; } return res; } int main() { matrix a; init(a); cin >> n; auto ans = matrix_quick_pow(a, n - 1); cout << ans.mxt[1][1] << endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具