矩阵
矩阵
顾名思义就是一个小破方阵
类似这样
0 0 1 1
0 1 0 1
0 1 1 1
0 0 0 0
这就是一个四行四列的矩阵,
矩阵包含三个信息, 长度, 宽度, 数值
数值就是矩阵里每一位上的数值, 通常用一个数值来存
为了方便使用我们常写成结构体形式
定义
struct Mat
{
int l, r; // 长, 宽
int a[N][N]; // 矩阵数组
};
那么矩阵有什么作用呢?
在定义中, 矩阵满足加, 减, 乘三种运算
矩阵加减
两个矩阵A, B可以加减的前提是他们的长宽对应相等
如下
A
1 2 3
4 5 6
7 8 9
3 4 2
B
5 3 3
4 5 8
9 9 9
7 7 7
这两个矩阵长宽相等于是可以加减
而矩阵加减非常简单, 就是对应位置加减, 就和普通运算一样, 具有交换律和结合律
如B - A
4 1 0
0 0 2
2 1 0
4 3 5
可得到如上矩阵
这就是矩阵加减, 因为很简单, 所以基本不考
代码
核心代码
struct Mat
{
int l, r;
int a[N][N];
}A, B, C;
Mat Mat_add(Mat &A, Mat &B) // 矩阵减同理
{
Mat temp;
temp = {A.l, A.r};
for (int i = 1; i <= A.l; i ++ )
for (int j = 1; j <= A.r; j ++ )
temp.a[i][j] = A.a[i][j] + B.a[i][j];
return temp;
}
具体代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100;
int n, m;
struct Mat
{
int l, r;
int a[N][N];
}A, B, C;
Mat Mat_add(Mat &A, Mat &B)
{
Mat temp;
temp = {A.l, A.r};
for (int i = 1; i <= A.l; i ++ )
for (int j = 1; j <= A.r; j ++ )
temp.a[i][j] = A.a[i][j] + B.a[i][j];
return temp;
}
void print(Mat &A)
{
for (int i = 1; i <= A.l; i ++ )
{
for (int j = 1; j <= A.r; j ++ )
printf("%-2d ", A.a[i][j]);
puts("");
}
puts("");
}
int main()
{
cin >> n >> m;
A = {n, m};
B = {n, m};
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
cin >> A.a[i][j];
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
cin >> B.a[i][j];
C = Mat_add(A, B);
print(C);
return 0;
}
矩阵乘法
相对于矩阵加减, 矩阵乘法就要重要很多
它的前提是两个矩阵A * B, A的宽度要等于, B的长度 (长度为上面定义中的l
,宽度为r
)
怎么乘呢?
设A
1 2 3
4 5 6
B
3 1
4 2
5 8
用A第i行的第k个数去乘, B第j列的第k个数, 得到的这r个结果相加就是新矩阵C的第i行第j列的数值
设i = 1, j = 2
那么就是
1 2 3 * 1
2
8
ans = 1 * 1 + 2 * 2 +3 * 8
那么C.a[i][j] = 1 * 1 + 2 * 2 +3 * 8 = 29
总结一下就是, A矩阵的第i行和B矩阵的第j列对应项相乘之和就是, 结果矩阵C的第i行第j列的结果
同时结果矩阵C的长度为A的长度, 宽度为B的宽度
那么A * B的结果矩阵C就是
26 29
48 62
刚开始学矩阵会很陌生, 但是不要紧, 多算算就熟练了
性质
因为其这个i行j列相乘的性质, 所以矩阵乘法是没有交换律的
你现在可以试试求求B * A 看看是否满足 B * A == A * B
虽然没有交换律, 但是它具有结合律, 也就是(A * B) * C == A * (B * C)
自己也可以试试, 这里不证明了
代码
看看代码吧
Mat Mat_mul(Mat &A, Mat &B, int p) // A * B 每一项取模 p, 返回结果矩阵
{
Mat temp = {A.l, B.r}; // 我们一般开一个矩阵存结果, 并在最后返回它
// 下面就是正常的计算, 请自行理解, 这里没法言传
for (int i = 1; i <= A.l; i ++ )
for (int j = 1; j <= B.r; j ++ )
for (int k = 1; k <= A.r; k ++ ) // A.r == B.l
temp.a[i][j] = (temp.a[i][j] + 1ll * A.a[i][k] * B.a[k][j]) % p;
// 记得防爆int
return temp;
}
这就是最基本的矩阵了
对于矩阵更重要的作用是[[矩阵快速幂]]