首先来认识什么是矩阵
定义:
在数学中,矩阵是一个按照长方阵列排列的复数或实数集合
这是一个很简单的定义。
矩阵的运算
矩阵加减法
对于两个相同大小的矩阵,直接把相同位置的元素相加即可,如下图:
(这个好像并没有什么用)
重点来了
矩阵乘法
对于两个矩阵,当且仅当其中一个矩阵的行与另一个矩阵的列时,两个矩阵相乘才有意义。
设(A)为(P×M)的矩阵,(B)为(M×Q)的矩阵,我们用一个矩阵(C)来存储矩阵(A)与矩阵(B)的乘积。
定义在矩阵乘法中,结果(C)矩阵的第(i)行第(j)列的数,就是由矩阵(A)第(i)行 (M)个数与矩阵(B)第(j)列(M)个数分别相乘再相加得到的
即:其中矩阵(C)中的第(i)行第(j)列元素可以表示为:
那么答案矩阵就可以表示成
举个例子
c++代码实现:
#include <cstdio>
#include <cstring>
const int MAXN = 1e3 + 5;
struct Matrix {
int mar[MAXN][MAXN];
int n, m;
Matrix() { memset(mar, 0, sizeof(mar)); }
void Matrix_Read() { //输入矩阵
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &mar[i][j]);
}
void Matrix_Write() { //输出矩阵
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++)
printf("%d ", mar[i][j]);
printf("
");
}
}
friend Matrix operator * (Matrix x, Matrix y) { //重载乘号并存储结果
Matrix res; res.n = x.n; res.m = y.m;
int sum;
for(int i = 0; i < x.n; i++) {
for(int j = 0; j < y.m; j++) {
sum = 0;
for(int k = 0; k < x.m; k++)
sum += x.mar[i][k] * y.mar[k][j];
res.mar[i][j] = sum;
}
}
return res;
}
};
Matrix A, B, C;
int main() {
scanf("%d %d", &A.n, &A.m); B.n = A.m;
A.Matrix_Read();
scanf("%d", &B.m);
B.Matrix_Read();
C = A * B;
C.Matrix_Write();
return 0;
}
输入:
2 3
1 2 3
3 2 1
2
1 1
2 2
3 3
输出:
2 3
1 2 3
3 2 1
2
1 1
2 2
3 3
重要性质:
矩阵乘法能很好地运用是因为矩阵乘法支持乘法交换律
即是:
(A×(B×C) =(A×B)×C)
运用
可以很大程度上优化动态规划时的过程。
就拿斐波拉契数列来举例:
(f(i)=f(i-1)+f(i-2);(i≤3))
很容易就想到一项一项地递推,时间复杂度为(O(n))。
但如果(n)达到(1e18)甚至更大的时候,可能跑一个上午都跑不出来。
这时候就可以使用矩阵加速。
我们定义一个矩阵([f(n-2),f(n-1)]),我们希望得到(f(n)),即需要([f(n-1),f(n)]),需要另一个矩阵来乘上([f(n-2),f(n-1)])。
因为(f(n)=f(n-1)+f(n-2))矩阵第一列应该是:
同理,矩阵第二列为:
所以
对于任意一个(n(n≥3))有,第(n)项为
其中矩阵([1, 1])表示([f(1), f(2)])
C++实现
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
ll N, MOD;
struct Matrix {
ll mar[5][5];
ll n, m;
Matrix() { memset(mar, 0, sizeof(mar)); }
void Matrix_Read() {
for(ll i = 0; i < n; i++)
for(ll j = 0; j < m; j++)
scanf("%lld", &mar[i][j]);
}
void Matrix_Write() {
for(ll i = 0; i < n; i++) {
for(ll j = 0; j < m; j++)
printf("%lld ", mar[i][j]);
printf("
");
}
}
friend Matrix operator * (Matrix x, Matrix y) {
Matrix res; res.n = x.n; res.m = y.m;
ll sum;
for(ll i = 0; i < x.n; i++) {
for(ll j = 0; j < y.m; j++) {
sum = 0;
for(ll k = 0; k < x.m; k++)
sum = (sum + x.mar[i][k] * y.mar[k][j]) % MOD;
res.mar[i][j] = sum;
}
}
return res;
}
};
Matrix model, Fib;
void Init();
void Run();
Matrix Power(ll);
int main() {
scanf("%lld %lld", &N, &MOD);
Init();
Run();
return 0;
}
void Init() {
Fib.mar[0][0] = 1;
Fib.mar[0][1] = 1;
model.mar[0][1] = 1;
model.mar[1][0] = 1;
model.mar[1][1] = 1;
Fib.n = 1;
Fib.m = model.n = model.m = 2;
}
void Run() {
N -= 2;
while(N) {
if(N & 1)
Fib = Fib * model;
model = model * model;
N >>= 1;
}
printf("%lld", Fib.mar[0][1] % MOD);
}
输入(n, m)
输出斐波拉契第(n)项对(m)取模后的值