矩阵运算
矩阵运算
众所周知,数是可以进行加减乘除的,那矩阵为啥不可以呢?
假设现在我们有两个矩阵
const int N = 110, mod = 1e9 + 7; // 矩阵大小和模数 struct matrix { int a[N][N], n, m; // 存储矩阵和矩阵大小 } ;
基本运算
矩阵加法
令
要求:
其实很简单,就是一一对应着加就行,即对于
所以
性质
- 交换律:明显满足,即
。 - 结合律:明显满足,即
。
单位矩阵
明显,就是一个大小为
矩阵加法 Code
时间复杂度:
matrix operator + (matrix y) { // 重载运算符 + matrix z; z.n = n, z.m = m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) z.a[i][j] = a[i][j] + y.a[i][j]; return z; }
矩阵乘法
令
要求:
公式:对于
似乎看起来没啥用?因为它是在某些特定方面可以进行时间优化(例如用 dp
等),单独拎出来出的题目很少(大多都是板子)。
性质
- 交换律:不满足!
- 若
,交换以后还能乘法,但矩阵大小会变为 ,与原矩乘后答案不同。 - 当然也有可能
,这样交换以后连矩乘的基本要求都无法满足。
- 若
- 结合律:满足,设还有一个矩阵
,大小为 , ,则 大小为 ,而 。 - 分配律:明显满足,设还有一个矩阵
,大小为 ,即 。
单位矩阵
提到矩乘,就不得不提到它的单位矩阵。
单位矩阵定义:若这个矩阵乘任意一个矩阵
观察式子,容易推出:当一个大小为
时间复杂度:
void Clear (int x, int y, int f) { // 把矩阵大小设为 x * y,矩阵元素都为 f n = x, m = y; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) a[i][j] = f; } void Unit (int x, int y) { // 构造单位矩阵 Clear(x, y, 0); // 先清空 for (int i = 1; i <= n; i++) a[i][i] = 1; // 只有主对角线为 1 }
矩阵乘法 Code
时间复杂度:
matrix operator * (matrix y) { // 重载运算符 * matrix z; z.n = n, z.m = y.m; for (int i = 1; i <= n; i++) for (int j = 1; j <= y.m; j++) { z.a[i][j] = 0; for (int k = 1; k <= m; k++) z.a[i][j] = (z.a[i][j] + 1ll * a[i][k] * y.a[k][j] % mod) % mod; // 套公式 } return z; }
矩阵除法
令
要求:同矩阵乘法。
由于浮点数不可以取模,数里面除法取模等于乘上除数的逆,所以矩阵除法同矩阵除法,不过是把
矩乘与它的特殊运算和应用
P3390 矩乘快速幂
给定一个矩阵
要求:矩阵的大小必须为
既然矩乘有结合律,那么就可以考虑使用类似于整数快速幂的方法以
矩乘快速幂 Code
时间复杂度:
matrix MATqmod (matrix x, ll y) { // 矩阵乘法快速幂 matrix sum; sum.Unit(x.n, x.m); // 初始化为单位矩阵 while (y) sum = (y & 1 ? sum * x : sum), x = x * x, y >>= 1; return sum; }
P1349 广义斐波那契数列
广义的斐波那契数列是指形如
的数列。 今给定数列的两系数
和 ,以及数列的最前两项 和 ,另给出两个整数 和 ,试求数列的第 项 。
令
观察一下,把相邻两项构成一个矩阵,即要从
要能与
套入公式,就是要求
普通的其实就相当于
Code
matrix c, d; int n, mod; c.Clear(2, 2, 0), d.Clear(1, 2, 0); cin >> c.a[1][1] >> c.a[2][1] >> d.a[1][2] >> d.a[1][1] >> n >> mod; if (n == 1) { cout << d.a[1][2]; return 0; } c.a[1][2] = 1, d = d * qmod(c, n - 2); cout << d.a[1][1];
完整代码
点击查看最新代码
#include <bits/stdc++.h> #define _1 (__int128)1 using namespace std; using ll = long long; void FileIO (string s) { freopen((s + ".in").c_str(), "r", stdin); freopen((s + ".out").c_str(), "w", stdout); } const int mod = 1e9 + 7, MATsize = 110; // 矩阵大小和模数 struct matrix { int a[MATsize][MATsize], n, m; // 存储矩阵和矩阵大小 void Clear (int x, int y, int f) { // 把矩阵大小设为 x * y,矩阵元素都为 f n = x, m = y; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) a[i][j] = f; } void Unit (int x, int y) { // 构造单位矩阵 Clear(x, y, 0); // 先清空 for (int i = 1; i <= n; i++) a[i][i] = 1; // 只有主对角线为 1 } matrix operator + (matrix y) { // 重载运算符 + matrix z; z.n = n, z.m = m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) z.a[i][j] = a[i][j] + y.a[i][j]; return z; } matrix operator * (matrix y) { // 重载运算符 * matrix z; z.n = n, z.m = y.m; for (int i = 1; i <= n; i++) for (int j = 1; j <= y.m; j++) { z.a[i][j] = 0; for (int k = 1; k <= m; k++) z.a[i][j] = (z.a[i][j] + 1ll * a[i][k] * y.a[k][j] % mod) % mod; // 套公式 } return z; } } ; matrix MATqmod (matrix x, ll y) { // 矩阵乘法快速幂 matrix sum; sum.Unit(x.n, x.m); // 初始化为单位矩阵 while (y) sum = (y & 1 ? sum * x : sum), x = x * x, y >>= 1; return sum; } signed main () { ios::sync_with_stdio(0), cin.tie(0); // FileIO(""); return 0; }
点击查看无注释代码
#include <bits/stdc++.h> #define _1 (__int128)1 using namespace std; using ll = long long; void FileIO (string s) { freopen((s + ".in").c_str(), "r", stdin); freopen((s + ".out").c_str(), "w", stdout); } const int mod = 1e9 + 7, MATsize = 110; struct matrix { int a[MATsize][MATsize], n, m; void Clear (int x, int y, int f) { n = x, m = y; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) a[i][j] = f; } void Unit (int x, int y) { Clear(x, y, 0); for (int i = 1; i <= n; i++) a[i][i] = 1; } matrix operator + (matrix y) { matrix z; z.n = n, z.m = m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) z.a[i][j] = a[i][j] + y.a[i][j]; return z; } matrix operator * (matrix y) { matrix z; z.n = n, z.m = y.m; for (int i = 1; i <= n; i++) for (int j = 1; j <= y.m; j++) { z.a[i][j] = 0; for (int k = 1; k <= m; k++) z.a[i][j] = (z.a[i][j] + 1ll * a[i][k] * y.a[k][j] % mod) % mod; } return z; } } ; matrix MATqmod (matrix x, ll y) { matrix sum; sum.Unit(x.n, x.m); while (y) sum = (y & 1 ? sum * x : sum), x = x * x, y >>= 1; return sum; } signed main () { ios::sync_with_stdio(0), cin.tie(0); // FileIO(""); return 0; }
本文作者:wnsyou
本文链接:https://www.cnblogs.com/wnsyou-blog/p/matrix.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步