1.什么是矩阵?

矩阵(数学术语)_百度百科


2.矩阵快速幂

首先要知道,只有n*n的矩阵能乘以自身(否则不符合矩阵相乘的条件)

然后要明白普通的快速幂的原理(本质是把幂次二分,代码如下)

inline int Pow(int a,int b){long long res=1, bs=a;while(b>0){if(b&1) res=res*bs%mod; bs=bs*bs%mod; b>>=1;}return res;
}

这里最终答案res从1开始,逐步让res乘以base值,以及让base值翻倍,从而达到了二分幂次的效果。

换成矩阵,思路完全一样。但是要进行两个替换:

  1. 把 res=1 换成 res等于一个单位矩阵。
  2. 数字相乘换成矩阵相乘,这一步可以用运算符重载来完成。

附上模板题链接和代码:【模板】矩阵快速幂 - 洛谷

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define int long long
#define pii pair<int,int>
const int N = 105, mod=1e9+7;
int n, k; //矩阵大小,矩阵次方
struct juzhen{int a[N][N];juzhen(){memset(a,0,sizeof(a));} //初始为0矩阵inline void build(){FOR(i,1,n) a[i][i]=1;} //建立单位矩阵void print(){FOR(i,1,n){FOR(j,1,n) cout<<a[i][j]<<' ';cout<<'\n';}}juzhen operator*(const juzhen& b){ //重载矩阵乘法juzhen res;FOR(i,1,n) FOR(j,1,n){FOR(k,1,n) res.a[i][j] = (res.a[i][j] + this->a[i][k]*b.a[k][j]%mod)%mod;}return res;}
}a;void solve(){cin>>n>>k;FOR(i,1,n) FOR(j,1,n) cin>>a.a[i][j];juzhen ans; ans.build(); //从一个单位矩阵开始while(k>0){ //矩阵快速幂计算if(k&1) ans=ans*a;a = a*a; k>>=1;}ans.print();
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int T=1; //cin>>T;while(T--) solve();
}

3.矩阵加速

矩阵加速可以用来计算一些dp的计算,加速的原理就是前面说到的矩阵快速幂。

1) 首先我们以一个简单的问题引入:斐波那契数列 - 洛谷

这就是普通的斐波那契数列,但是n值达到了恐怖的2e9,显然原本O(n)的普通dp思路不可行。

那么,我们就要用到矩阵加速了。

考虑构造一个1*2的矩阵,用这个矩阵进行递推。

由斐波那契的递推式

得到矩阵的递推式

再得到最终的计算式

最终代码如下:

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define int long long
#define pii pair<int,int>
const int mod = 1e9+7;
int n;struct node{int a[3][3];node(){memset(a,0,sizeof(a));} //初始为0矩阵void build(){a[1][1]=0,a[1][2]=a[2][1]=a[2][2]=1;} //建立变换矩阵node operator*(const node&b){node res;FOR(i,1,2) FOR(j,1,2){FOR(k,1,2) res.a[i][j] = (res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;}return res;}
};
node Pow(node a, int b){node res; res.a[1][1]=res.a[2][2]=1; //建立res为单位矩阵while(b>0){ //矩阵快速幂if(b&1) res=res*a;a=a*a; b>>=1;}return res;
}
pii cheng(pii a, node b){pii res;res.first = (a.first*b.a[1][1]%mod + a.second*b.a[2][1]%mod)%mod;res.second = (a.first*b.a[1][2]%mod + a.second*b.a[2][2]%mod)%mod;return res;
}
void solve(){cin>>n;node a; a.build();a = Pow(a,n-1);cout<<cheng({0,1},a).second<<'\n';
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int T=1; //cin>>T;while(T--) solve();
}

2) 再推广到一般的矩阵加速,也是一样的做法,看下这道题:【模板】矩阵加速(数列) - 洛谷

容易得到矩阵转移式为:

所以这次的转换矩阵就变成了

最终代码如下:

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define int long long
#define pii pair<int,int>
const int mod = 1e9+7;
int n;struct node{int a[4][4];node(){memset(a,0,sizeof(a));} //初始为0矩阵void build(){a[1][3]=a[2][1]=a[3][2]=a[3][3]=1;} //建立变换矩阵node operator*(const node&b){node res;FOR(i,1,3) FOR(j,1,3){FOR(k,1,3) res.a[i][j] = (res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;}return res;}void print(){FOR(i,1,3){FOR(j,1,3) cout<<a[i][j]<<' ';cout<<'\n';}}
};
node Pow(node a, int b){node res; res.a[1][1]=res.a[2][2]=res.a[3][3]=1; //建立res为单位矩阵while(b>0){ //矩阵快速幂if(b&1) res=res*a;a=a*a; b>>=1;}return res;
}
struct tii{int a[4];tii(){memset(a,0,sizeof(a));}tii(int x,int y,int z){a[1]=x,a[2]=y,a[3]=z;}
};
tii cheng(tii a,node b){tii res;FOR(i,1,3){FOR(j,1,3) res.a[i] = (res.a[i] + a.a[j]*b.a[j][i]%mod)%mod;}return res;
}
void solve(){cin>>n;node a; a.build();a = Pow(a,n-1);cout<<cheng(tii(0,0,1),a).a[3]<<'\n';
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int T=1; cin>>T;while(T--) solve();
}

矩阵小专题(矩阵快速幂+矩阵加速)相关推荐

  1. hdu 4549 M斐波那契数列(费马小定理 + 二分快速幂 + 矩阵快速幂)

    M斐波那契数列                                                                           Time Limit: 3000/1 ...

  2. 快速幂+矩阵快速幂模板

    快速..运算 快速幂 运用位运算 代码 分析 矩阵快速幂 题目 分析 代码 拓一..: 快速幂 运用位运算 强大的位运算把我搞得蒙蒙的 理解了之后我表示很喜欢!!! 代码 int power(int ...

  3. 【bzoj4870】[Shoi2017]组合数问题 dp+快速幂/矩阵乘法

    题目描述 输入 第一行有四个整数 n, p, k, r,所有整数含义见问题描述. 1 ≤ n ≤ 10^9, 0 ≤ r < k ≤ 50, 2 ≤ p ≤ 2^30 − 1 输出 一行一个整数 ...

  4. 快速幂+矩阵快速幂(总结+例题)

    1.快速幂 以求a的b次方来介绍: 首先把b转换成二进制数 该二进制数第i位的权为  2^i - 1 . 比如 : 11的二进制是1011 11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1 ...

  5. 快速幂 + 矩阵快速幂

    快速幂 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #define LL lo ...

  6. 矩阵的乘法和快速幂的一些理解(适用初学者)

    矩阵是线性代数的知识...后悔没好好学了... 第一部分:矩阵的基础知识 1.结合性 (AB)C=A(BC). 2.对加法的分配性 (A+B)C=AC+BC,C(A+B)=CA+CB . 3.对数乘的 ...

  7. (十进制快速幂+矩阵优化)BZOJ 3240 3240: [Noi2013]矩阵游戏

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3240 3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  M ...

  8. 蓝桥杯:垒骰子【快速幂+矩阵乘法解决动态规划问题】

    先看题: [说实话,这道题是本菜写过最有数学味道的题目,虽然是是简单的矩阵运算和快速幂] 这道题目如果数据范围小的话,那么就是一个简单的dp,为了方便理解,我们先看不考虑时间复杂度的问题,先来看下怎么 ...

  9. 40行代码AC_HDU 1575 TrA 矩阵快速幂(附快速幂+矩阵快速幂的讲解)

    一道经典的矩阵快速幂模板题. 传送门1-->快速幂基本思想 传送门2-->矩阵快速幂讲解(教主传授) 心路历程 1.开始看成求主对角线元素和的n次幂了,用快速幂解得.结果压根不对,又仔细看 ...

最新文章

  1. Android--解析XML之SAX
  2. Python安装MySQL库详解(解决Microsoft Visual C++ 9.0 is required )
  3. Linux内核 scatterlist介绍
  4. ubuntu开机时网络图标不见了且不能上网
  5. Python破解百度翻js代码
  6. python自动化办公都能做什么-用 Python 自动化办公,我与大神之间的差距一下就...
  7. Linux的版本可分为,Linux不同分类标准下的各种版本解读
  8. 3500个常用汉字列表
  9. 微信企业号上传永久素材讲解与演示
  10. SOFA Weekly | QA 整理
  11. wordpress php教程 pdf,wordpress
  12. Mac关闭“屏幕截图”和“清倒废纸篓”音效
  13. 微信文章排版技巧和相关排版工具
  14. C语言——深度剖析数据在内存中的存储
  15. Appium(Python)测试混血App
  16. Android仿学习强国填空题考试界面
  17. CAD文件怎么转成低版本?教你两个小妙招
  18. Zotero(1)---文献管理软件Zotero安装教程
  19. JS 事件冒泡、捕获。学习记录
  20. SumatraPDF反向搜索命令行设置

热门文章

  1. 程序员面试题精选100题:求从1到n的正数中1出现的次数
  2. 【VMware vSAN 7.0】2.5 许可证要求 —我们有软硬件解决方案
  3. 使用opengl绘制立方体_一步步学OpenGL(25) -《Skybox天空盒子》
  4. 手游录屏直播技术详解 | 直播 SDK 性能优化实践
  5. 《C专家编程》:如何用气压计测量建筑物的高度(附3)
  6. sinx除以x²积分怎么算
  7. 每年都说Java市场已经饱和,那Java到底是不是真的饱和了呢?
  8. 1.4 Python程序语法元素分析 | Python语言程序设计(嵩天)
  9. Android 12 apk Installation did not succeed
  10. linux编程之经典多级时间轮定时器(C语言版)