关于矩阵快速幂的一点点理解
本文有一些地方引用了博客:矩阵快速幂基础讲解 - 林夕-梦 - 博客园 (cnblogs.com)
如果有侵权请联系删除
矩阵快速幂算法篇
看了一个整数数的快速幂,现在我们就正式介绍矩阵快速幂算法。假如现在有一个n*n的方阵A。所谓方阵就是行数和列数相等的矩阵,先给出一个数M,让算矩阵A的M次幂,A^M.在此只要求计算并不需要去深究这个矩阵到底是什么含义。则上面代码可以化为。
上面只是简单的计算矩阵的幂,大家会感觉很抽象,因为上述矩阵并没有具体的含义,
现在就举例说明矩阵快速幂在实际运用中的意义:
以最常见的斐波那契数列为例:众所周知:斐波那契数列递推公式为:
F[n] = F[n-1] + F[n-2]. 由f[0]=0,f[1]=1,可以递推后面的所有数。
在以前,我们会常常用for循环,这是最直接的算法。
矩阵快速幂可以解决形似斐波那契数列的拓展形式以及变形形式,并且能够解决当n比较大的时候,注意其中的推导过程
贴一个下午矩阵快速幂模板题目的代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef struct { ll mp[10][10]; }node; node ans,res; const ll mod = 1000000000 + 7; node mul(node A,node B) { node tmp; //初始化临时矩阵,用于存放A * B的结果 for(int i = 1;i <= 2;i++) { for(int j = 1;j <= 2;j++) { tmp.mp[i][j]=0; } } //矩阵相乘并且返回 for(int i = 1;i <= 2;i++) { for(int j = 1;j <= 2;j++) { for(int k = 1;k <= 2;k++) { (tmp.mp[i][j] += A.mp[i][k] * B.mp[k][j] % mod) % mod; } } } return tmp; } void quick_pow(ll n,ll m) { //定义一个单位矩阵,因为单位矩阵乘以任何一个矩阵都是其矩阵本身 for(int i = 1;i <= 2;i++) { for(int j = 1;j <= 2;j++) { if(i == j) ans.mp[i][j] = 1; else ans.mp[i][j] = 0; } } while(m) { if(m & 1) { ans = mul(ans,res); } res = mul(res,res); m >>= 1; } } void pre() { res.mp[1][1] = 3; res.mp[1][2] = (-1 + mod) % mod; res.mp[2][1] = 1; res.mp[2][2] = 0; } int T; ll tmp; int main() { scanf("%d",&T); while(T--) { scanf("%lld",&tmp); if(tmp == 1) { printf("1\n"); } else if(tmp == 2) { printf("2\n"); } else { pre(); quick_pow(2,tmp - 2); // for(int i = 1;i <= 2;i++) // { // for(int j = 1;j <= 2 ;j++) // { // printf("%lld ",ans.mp[i][j]); // } // printf("\n"); // } // printf("---------------------------\n"); // for(int i = 1;i <= 2;i++) // { // for(int j = 1;j <= 2 ;j++) // { // printf("%d ",res.mp[i][j]); // } // printf("\n"); // } ll final = ((ans.mp[1][1] * 2) % mod + ans.mp[1][2]) % mod; printf("%lld\n",final); } } return 0; }
注意矩阵快速幂的取模,如果存在矩阵系数是负数的时候要先在设置矩阵的时候进行取模,不然会因为各种原因爆掉

浙公网安备 33010602011771号