线性代数是算法学习中的重要数学基础,而矩阵乘法更是其中的核心内容,不仅是理解后续矩阵快速幂、矩阵加速的前提,还广泛应用于图论邻接矩阵、动态规划优化、数列求解等算法场景。本文将从矩阵的基本概念出发,一步步拆解矩阵乘法的定义、运算规则,再结合洛谷经典真题,手把手实现矩阵乘法、矩阵快速幂的 C++ 模板,同时讲解矩阵加速在数列求解中的实际应用,让零基础的同学也能彻底吃透矩阵乘法!下面就让我们正式开始吧!
在正式学习矩阵乘法前,我们首先要搞清楚什么是矩阵,以及算法中常用的特殊矩阵有哪些。这些基础概念是后续所有运算的前提,理解透彻才能避免后续踩坑。
简单来说,矩阵就是由n×m 个数字排成的n 行 m 列的数表,我们通常用大写字母 A、B、C 来表示矩阵,其中第 i 行第 j 列的元素记作aij。其标准形式如下:

比如一个 2 行 3 列的矩阵可以表示为

,这就是一个 2×3 矩阵。
在算法中,矩阵的一个典型应用就是图论的邻接矩阵—— 用一个 n×n 的矩阵存储 n 个节点的图,若节点 i 和节点 j 之间有边,则aij=1,否则为 0,通过邻接矩阵可以快速判断节点间的连通性,而邻接矩阵的运算本质就是矩阵乘法。
在矩阵乘法的运算中,我们会经常遇到几种特殊的方阵(行数 = 列数的矩阵),它们各自有独特的性质,更是矩阵快速幂、单位矩阵运算的关键,下面逐个讲解,结合例子理解更直观。
行数等于列数的矩阵称为方阵,比如 4×4、3×3 矩阵都是方阵。方阵中从左上角到右下角的元素构成主对角线,后续的三角矩阵、对角矩阵都是基于方阵的主对角线定义的。例:4 阶方阵(4×4)

三角矩阵分为上三角矩阵和下三角矩阵,核心是主对角线一侧的元素全为 0:
例:4 阶上三角矩阵

例:4 阶下三角矩阵

主对角线之外的元素均为 0的方阵称为对角矩阵,简单说就是只有主对角线上有非 0 元素,其余位置全 0。对角矩阵是三角矩阵的特殊形式,上三角和下三角矩阵的交集就是对角矩阵。例:4 阶对角矩阵

主对角线的元素均为 1的对角矩阵称为单位矩阵,通常用字母 E 表示。单位矩阵是矩阵乘法中的 “数字 1”,任何矩阵乘以单位矩阵,结果都等于原矩阵,即AE=EA=A,这一性质是矩阵快速幂的核心基础,一定要牢记!
例:4 阶单位矩阵

在学习矩阵乘法前,我们先掌握矩阵的线性运算—— 加法、减法和数乘,这些运算规则简单,是理解复杂运算的铺垫,核心要求是同型矩阵(行数和列数都相同的矩阵)。
矩阵加减法的规则非常直观:两个同型矩阵相加减,结果为对应位置的元素分别相加减。

矩阵数乘指的是一个数字乘以一个矩阵,规则是:矩阵中的每一个元素都乘以这个数字,结果矩阵的行数和列数不变。这里的 “数” 可以是整数、小数,正数、负数均可,数乘是对矩阵的整体缩放,不会改变矩阵的维度。

矩阵的加法和数乘满足交换律、结合律和分配律,和我们小学学的数字运算规律基本一致,记起来很容易:
这些规律看似简单,但在后续的矩阵运算化简中会经常用到,熟悉后能大幅提高运算效率。
矩阵乘法是本文的核心重点,也是和普通数字运算差异最大的部分,其规则不是简单的对应元素相乘,而是 “行乘列求和”,且有严格的维度要求,很多同学初次学习容易出错,建议结合例子反复理解。
矩阵 A 和矩阵 B 能够相乘的唯一前提:矩阵 A 的列数 = 矩阵 B 的行数。如果不满足这个条件,矩阵乘法无意义,无法进行运算。比如:
若 A 是 n×s 矩阵,B 是 s×m 矩阵,那么 A×B 的结果是一个n×m 矩阵(n 行 m 列),记为 C=AB。
简单总结:结果矩阵的行数等于第一个矩阵的行数,列数等于第二个矩阵的列数,而中间的 “s” 是两个矩阵的 “公共维度”,是行乘列求和的次数。
例:2×3 矩阵 × 3×4 矩阵 = 2×4 矩阵;3×5 矩阵 ×5×2 矩阵 = 3×2 矩阵。
设 C=AB,其中 A 是 n×s 矩阵,B 是 s×m 矩阵,C 是 n×m 矩阵,那么 C 中第 i 行第 j 列的元素cij的计算公式为:

用通俗的语言解释就是:cij等于矩阵 A 的第 i 行所有元素,与矩阵 B 的第 j 列对应位置元素分别相乘后,再将所有乘积相加,也就是我们常说的 “行乘列求和”。
这里的 k 从 1 到 s,对应 A 的第 i 行有 s 个元素,B 的第 j 列有 s 个元素,刚好一一对应相乘,求和后得到cij。
光看公式和定义容易抽象,我们用一个具体的例子,手把手计算矩阵乘法,把 “行乘列求和” 的规则落地,看完这个例子,矩阵乘法的计算就基本掌握了。

步骤 1:判断是否可乘 + 确定结果维度A 的列数 = 2,B 的行数 = 2,满足条件;结果 C 是 3×3 矩阵(n=3,m=3)。
步骤 2:逐行逐列计算cijC 是 3 行 3 列,需要计算 9 个元素,逐个计算:
步骤 3:整理结果矩阵C=AB=

矩阵乘法的运算规律和普通数字乘法有很大差异,最核心的区别是不满足交换律,这一点是算法编程中必须注意的,一旦顺序写错,结果完全错误!下面总结矩阵乘法的核心规律:
一般情况下,AB≠BA,甚至 BA 可能无意义。
原因有两点:
结论:矩阵乘法中,顺序决定一切,AB 表示 A 左乘 B,BA 表示 B 左乘 A,二者完全不同,编程时必须严格按照题目要求的顺序相乘。
A(BC)=(AB)C,即多个矩阵相乘时,改变括号的位置(运算顺序),结果不变。
结合律是矩阵快速幂的核心数学基础,正因为有结合律,我们才能像整数快速幂那样,将Ak拆解为多个小矩阵的乘积,实现对数级别的时间复杂度优化。
注意:分配律中也要注意顺序,左分配律中 A 始终在左边,右分配律中 A 始终在右边,不能随意交换。
任何矩阵乘以单位矩阵,结果等于原矩阵,即AE=EA=A(前提是相乘维度满足条件)。
比如 A 是 n×s 矩阵,E 是 s×s 单位矩阵,则 AE=A;E 是 n×n 单位矩阵,则 EA=A。单位矩阵的这一性质,对应整数乘法中的 “1×x=x×1=x”,是矩阵快速幂中初始值的设置依据。
理解了矩阵乘法的定义和规则后,我们结合洛谷的基础真题B2105 矩阵乘法,用 C++ 实现基础的矩阵乘法模板。这道题是矩阵乘法的入门题,核心是模拟 “行乘列求和” 的过程,适合新手上手。
题目链接:https://www.luogu.com.cn/problem/B2105
计算两个矩阵的乘法:n×m 阶的矩阵 A 乘以 m×k 阶的矩阵 B,得到 n×k 阶的矩阵 C。
#include <iostream>
using namespace std;
// 定义数组大小,留余量避免越界
const int N = 110;
// a:矩阵A, b:矩阵B, c:结果矩阵C
int a[N][N], b[N][N], c[N][N];
// n:A的行, m:A的列/B的行, s:B的列(题目中的k)
int n, m, s;
// 矩阵乘法核心函数
void mul() {
for (int i = 1; i <= n; i++) { // 遍历A的行
for (int j = 1; j <= s; j++) { // 遍历B的列
for (int k = 1; k <= m; k++) { // 遍历公共维度m
c[i][j] += a[i][k] * b[k][j];
}
}
}
}
int main() {
cin >> n >> m >> s;
// 输入矩阵A
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
}
}
// 输入矩阵B
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= s; j++) {
cin >> b[i][j];
}
}
// 执行矩阵乘法
mul();
// 输出结果矩阵C
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= s; j++) {
cout << c[i][j] << " ";
}
cout << endl;
}
return 0;
}掌握了基础矩阵乘法后,我们来学习矩阵乘法的进阶应用 —— 矩阵快速幂,这是算法竞赛中的高频考点,核心是类比整数快速幂,利用矩阵乘法的结合律,将Ak的计算时间复杂度从O(k)优化到O(logk),适用于 k 极大的场景(比如 k≤10^18)。
整数快速幂的核心是 “快速幂降次”,比如计算

,可以拆解为

,而不是连续乘 10 次 x。矩阵快速幂完全复用这一思想,唯一的区别是:
简单来说,矩阵快速幂的步骤为:
题目链接:https://www.luogu.com.cn/problem/P3390

洛谷 P3390 【模板】矩阵快速幂:给定 n×n 的矩阵 A,求Ak,结果矩阵的每个元素对109+7取模。
*,实现两个矩阵的相乘,同时完成取模操作,简化代码;#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 110;
const int MOD = 1e9 + 7; // 取模模数
LL n, k; // n:矩阵阶数, k:指数
// 矩阵结构体
struct Matrix {
LL m[N][N];
// 构造函数,初始化矩阵为全0
Matrix() {
memset(m, 0, sizeof(m));
}
// 重载乘法运算符,实现矩阵乘法
Matrix operator*(const Matrix& B) const {
Matrix C; // 结果矩阵
for (int i = 1; i <= n; i++) { // 遍历A的行
for (int j = 1; j <= n; j++) { // 遍历B的列
for (int t = 1; t <= n; t++) { // 遍历公共维度
C.m[i][j] = (C.m[i][j] + m[i][t] * B.m[t][j]) % MOD;
}
}
}
return C;
}
}A, ret; // A:原始矩阵, ret:结果矩阵(初始为单位矩阵)
// 矩阵快速幂函数
void qpow(LL b) {
// 初始化结果矩阵为单位矩阵
for (int i = 1; i <= n; i++) {
ret.m[i][i] = 1;
}
while (b) {
if (b & 1) { // 若当前二进制位为1,结果矩阵乘当前A
ret = ret * A;
}
A = A * A; // 矩阵自乘
b >>= 1; // 指数右移一位,等价于除以2
}
}
int main() {
cin >> n >> k;
// 输入原始矩阵A
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;
}*运算符后,矩阵相乘可以直接写为A*B,和整数乘法一样直观,大幅简化代码,避免重复写矩阵乘法的三层循环;b & 1判断当前二进制位是否为 1,b >>= 1实现指数降次,这是快速幂的标准操作,时间复杂度为O(logk),即使 k=10^18,也只需循环 60 次左右,效率极高。矩阵快速幂的核心应用是矩阵加速,用于求解线性递推数列的第 n 项,比如斐波那契数列、递推式为ax=ax−1+ax−3的数列等。对于递推数列,当 n 极大时(比如 n≤10^18),动态规划的 O (n) 算法会超时,而矩阵加速结合快速幂可以将时间复杂度优化到 O (logn),这是算法竞赛中的经典优化手段。
矩阵加速的关键是构造递推矩阵(也叫转移矩阵),将数列的线性递推关系转化为矩阵的幂次运算,即:转移矩阵其中 k 是递推式的初始项数,比如斐波那契数列的递推式是Fn=Fn−1+Fn−2,初始项是 F1=1、F2=1,k=2。
简单来说,矩阵加速的步骤为:
题目链接:https://www.luogu.com.cn/problem/P1962
斐波那契数列是最经典的线性递推数列,递推式为:F1=1,F2=1,Fn=Fn−1+Fn−2(n≥3)我们用矩阵加速结合快速幂,求解

。
首先,将斐波那契的递推式转化为矩阵形式:

验证:右边矩阵相乘的结果为

,与左边一致。
由此可以推导出通式:

转移矩阵就是

,初始项矩阵是

。
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 3;
const int MOD = 1e9 + 7;
LL 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 <= 2; i++) {
for (int j = 1; j <= 2; j++) {
for (int t = 1; t <= 2; t++) {
C.m[i][j] = (C.m[i][j] + m[i][t] * B.m[t][j]) % MOD;
}
}
}
return C;
}
}A, ret;
// 矩阵快速幂
void qpow(LL b) {
// 初始化结果矩阵的初始值(对应初始项[F2,F1])
ret.m[1][1] = 1;
ret.m[1][2] = 1;
// 构造转移矩阵
A.m[1][1] = 1; A.m[1][2] = 1;
A.m[2][1] = 1; A.m[2][2] = 0;
while (b) {
if (b & 1) {
ret = ret * A;
}
A = A * A;
b >>= 1;
}
}
int main() {
cin >> n;
// 初始项直接输出
if (n == 1 || n == 2) {
cout << 1 << endl;
return 0;
}
// 计算转移矩阵的n-2次幂
qpow(n - 2);
// 结果为ret.m[1][1]
cout << ret.m[1][1] << endl;
return 0;
}矩阵乘法看似抽象,但只要掌握了核心规则和模板,再结合真题反复练习,就能彻底吃透。作为算法学习的重要基础,矩阵乘法的掌握程度直接影响后续复杂算法的学习,希望本文能帮助大家从入门到实战,彻底搞懂矩阵乘法!