通过查询本喵的获奖记录可以看到,我只有 5 级钩,所以可能不会讲得很深,但应该不会出错。
一、矩阵定义
把若干个数字排成一个矩形表,就是 矩阵。
例如:
[acbd]
通常记作:
A=(aij)m×n
其中:
- m 表示行数;
- n 表示列数;
- aij 表示第 i 行第 j 列的元素。
二、常用概念
主对角线是指从左上角到右下角的对角线。
三、矩阵的加减法
只有同型矩阵才可以进行加减运算,即两个矩阵的行数和列数分别相等。
运算规则:对应位置上的元素相加减。
例如:
[1234]+[5768]=[1+52+73+64+8]=[69912]
四、矩阵乘法
我觉得这部分最难了,也可能是本喵太菜了。
1. 乘法条件
若矩阵 A 是 m×n 的矩阵,矩阵 B 是 n×p 的矩阵,则它们可以相乘:
C=AB
结果 C 是一个 m×p 的矩阵。
也就是说:
A 的列数等于 B 的行数才可相乘(当然,把这句话反过来说,也就是“B 的行数等于 A 的列数”,意思是一样的喵)。
2. 乘法规则
接上条,设:
C=AB
则 C 的第 i 行第 j 列的元素为:
cij=k=1∑naikbkj
用喵话说,就是:
A 的第 i 行与 B 的第 j 列的对应元素相乘后再相加。
例如:
A=[1324],B=[5768]
计算 C=AB:
c11=1⋅5+2⋅7=19
c12=1⋅6+2⋅8=22
c21=3⋅5+4⋅7=43
c22=3⋅6+4⋅8=50
所以:
C=[19432250]
3. 特殊性质
-
矩阵乘法不满足交换律,即 AB=BA。
-
矩阵乘法满足结合律,即 (AB)C=A(BC)。
-
矩阵乘法满足分配律,即 A(B+C)=AB+AC。
五、方阵的幂
显然只有方阵才能自己乘自己。
定义:
Ak=k 个AA⋯A
特别地,约定:
A0=I
六、矩阵快速幂
矩阵快速幂和普通整数快速幂的思想完全一样:将指数按二进制拆分,利用幂的运算性质加速。
我们要计算 Ab,其中 A 是方阵。
如果直接乘 b 次,复杂度是 O(b⋅n3),当 b 很大时不可接受。
快速幂做法:
把指数 b 写成二进制。例如:
b=13=11012
那么:
A13=A8⋅A4⋅A1
我们只需要维护一个底数 base=A2k,每次让 base 自己乘自己,就能得到 A1,A2,A4,A8,⋯。
如果当前二进制位是 1,就把结果乘上这个 base。
算法流程
设结果矩阵 res=I,底数矩阵 base=A。
当 b>0 时:
- 如果 b 的最低位是 1,则 res=res×base;
- 令 base=base×base;
- 令 b=b>>1。
最后 res=Ab。
复杂度:一次矩阵乘法是 O(n3),快速幂需要乘 O(logb) 次,总复杂度 O(n3logb)。
七、矩阵快速幂优化递推
终于到了喵。
例子:斐波那契数列
斐波那契数列的定义:
F0=0,F1=1
Fn=Fn−1+Fn−2
直接递推求解显然为 O(n),但可以使用今天的内容优化到 O(logn)。
构造转移矩阵
我们把当前需要的两项打包成一个列向量:
vn=[FnFn−1]
那么下一项:
vn+1=[Fn+1Fn]
观察:
Fn+1=1⋅Fn+1⋅Fn−1
Fn=1⋅Fn+0⋅Fn−1
所以转移矩阵为:
M=[1110]
于是:
vn+1=Mvn
连续递推可得:
vk=Mkv0
其中初始向量:
v0=[F1F0]=[10]
因此求 Fk,只需计算 Mk,然后乘上 v0,结果向量的第二行就是 Fk。
另外,通过归纳法可以证明:
Mk=[Fk+1FkFkFk−1]
所以也可以直接取 Mk 的第一行第二列。
一般二阶线性递推
如果递推形式是:
an=p⋅an−1+q⋅an−2
同样把当前两项打包:
vn=[anan−1]
那么:
an+1=p⋅an+q⋅an−1
an=1⋅an+0⋅an−1
所以转移矩阵为:
M=[p1q0]
更高阶递推
若递推式涉及前 d 项,则需要维护 d 维列向量,转移矩阵为 d×d,第一行放递推系数,下面各行负责把旧分量向下搬运。
例如递推式:
an=p⋅an−1+q⋅an−2+r⋅an−3
转移矩阵为:
p10q01r00
规律非常明显喵。
至此,矩阵快速幂优化递推的核心思想就讲完了。总结一下:
- 确定状态向量;
- 写出递推关系;
- 构造转移矩阵;
- 快速幂求解。
有帮助,赞一个