一、矩阵相关概念
【矩阵】
由n×m个数排成n行m列的数表称为n行m列的矩阵,简称n×m矩阵。记作:
在学习图论时,存储图的一种方式------邻接矩阵,就是矩阵。所以矩阵用二维数组就可以存储。
【特殊的矩阵】
1、方阵
行数等于列数的矩阵称为方阵。方阵中行数等于列数的元素构成主对角线。
2、三角矩阵
如果方阵主对角线左下方的元素均为0,称为上三角矩阵。例如:
如果方阵主对角线右上方的元素均为0,称为下三角矩阵。例如:
3、对角矩阵
主对角线之外的元素均为0的方阵称为对角矩阵。例如:
4、单位矩阵
主对角线的元素均为1的对角矩阵。例如:
【矩阵的运算】
1、加法、减法和数乘
两个矩阵的加减法为对应元素分别作加减法。注意:只有同型矩阵之间可以做对应相加减!
数乘即为矩阵乘以一个数,结果为矩阵中每个元素都乘以这个数。
矩阵的加减与数乘称为矩阵的线性运算。
2、矩阵乘法
矩阵相乘时只有第一个矩阵的列数 与第二个矩阵的行数相同时才有意义!
设A为n×s的矩阵,B为s×m的矩阵,那么矩阵A与矩阵B的乘积为n×m的矩阵C,其中cij表示矩阵A的第i行与矩阵B的第j列元素分别相乘再相加。

【矩阵的运算规律】
1、线性运算满足交换律、结合律、分配律
·A+B = B+A
·A+B+C = A+(B+C)
·k*(A+B)= k*A + k*B
2、矩阵乘法只满足结合律和分配律
·ABC = A(BC)
·A(B+C) = AB + AC
注意:矩阵乘法可能不满足交换律。因此,在计算矩阵乘法时,前后顺序很重要!
特殊的,任何矩阵乘单位矩阵E,都不会改变:AE = EA = A 。因此,单位矩阵相当于数字1。
二、【模板】矩阵乘法

cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 110;
int n, m, s;
int a[N][N], b[N][N], c[N][N];
int main()
{
cin >> n >> m >> s;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
cin >> a[i][j];
for (int i = 1;i <= m;i++)
for (int j = 1;j <= s;j++)
cin >> b[i][j];
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= s;j++)
{
for (int k = 1;k <= m;k++)
{
c[i][j] += a[i][k] * b[k][j];
}
}
}
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= s;j++)
{
cout << c[i][j] << " ";
}
cout << endl;
}
return 0;
}
三、【模板】矩阵快速幂


cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 110, mod = 1e9 + 7;
LL k, n;
// 矩阵的结构体
struct matrix
{
LL m[N][N];
// 构造函数
matrix()
{
memset(m, 0, sizeof m);
}
// 重载乘法运算符
matrix operator*(const matrix& B) const
{
matrix C;
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= n;j++)
{
for (int k = 1;k <= n;k++)
{
C.m[i][j] = (C.m[i][j] + m[i][k] * B.m[k][j]) % mod;
}
}
}
return C;
}
}A, RET;
void qpow(LL b)
{
// 把RET变为单位矩阵
for (int i = 1;i <= n;i++)
RET.m[i][i] = 1;
while (b)
{
if (b & 1)
{
RET = RET * A;
}
b >>= 1;
A = A * A;
}
}
int main()
{
cin >> n >> k;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= n;j++)
cin >> A.m[i][j];
qpow(k);
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= n;j++)
{
cout << RET.m[i][j] << " ";
}
cout << endl;
}
return 0;
}
四、【练习】矩阵加速

解法:利用矩阵快速幂加速递推,构造出矩阵相乘的形式。

cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 5, mod = 1e9 + 7;
struct matrix
{
LL m[N][N];
matrix()
{
memset(m, 0, sizeof m);
}
matrix operator*(const matrix& B) const
{
matrix C;
for (int i = 1;i <= 3;i++)
{
for (int j = 1;j <= 3;j++)
{
for (int k = 1;k <= 3;k++)
{
C.m[i][j] = (C.m[i][j] + m[i][k] * B.m[k][j]) % mod;
}
}
}
return C;
}
void clear()
{
memset(m, 0, sizeof m);
}
}A, RET;
void qpow(LL b)
{
RET.m[1][1] = RET.m[1][2] = RET.m[1][3] = 1;
A.m[1][1] = A.m[1][2] = A.m[2][3] = A.m[3][1] = 1;
while (b)
{
if (b & 1)
RET = RET * A;
b >>= 1;
A = A * A;
}
}
int main()
{
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
A.clear();
RET.clear();
if (n == 1 || n == 2 || n == 3)
{
cout << 1 << endl;
continue;
}
qpow(n - 3);
cout << RET.m[1][1] << endl;
}
return 0;
}