矩阵
定义
设 \(m,n\) 是两个正整数,由数域 \(\mathbb{F}\) 中 \(m\times n\) 个数 \(a_{i,j}\) 排成的一个 \(m\) 行 \(n\) 列的矩形图表叫做矩阵 \(\mathbf{A}\)(或 \((a_{i,j})\) 和 \((a_{i,j})_{m\times n}\)),表示为:
称为 \(\mathbb{F}\) 上的一个 \(m\) 行 \(n\) 列的矩阵或 \(m\times n\) 矩阵。特别地,当 \(m=n\) 时,称 \(m\times n\) 矩阵 \(\mathbf{A}\) 是一个 \(n\) 阶方阵。
记 \(M_{m,n}(\mathbb{F})=\{\mathbf{A}=(a_{i,j})_{m\times n}\mid a_{i,j}\in \mathbb{F}\}\) 为数域 \(\mathbb{F}\) 上的所有 \(m\times n\) 矩阵全体,\(M_n(\mathbb{F})=M_{n,n}(\mathbb{F})\) 为数域 \(\mathbb{F}\) 上的所有 \(n\) 阶方阵全体。
矩阵乘法
有两个矩阵 \(\mathbf{A}=(a_{i,j})_{m\times n},\mathbf{B}=(b_{i,j})_{n\times s}\),定义 \(\mathbf{A}\) 与 \(\mathbf{B}\) 的乘积为矩阵 \(\mathbf{C}=(c_{i,j})\in M_{m,s}(\mathbb{F})\),其中:
即:\(\mathbf{C}\) 矩阵的第 \(i\) 行第 \(j\) 列的数,就是由矩阵 \(\mathbf{A}\) 第 \(i\) 行 \(n\) 个数与矩阵 \(\mathbf{B}\) 第 \(j\) 列 \(n\) 个数对应位置相乘再相加得到的。
矩阵乘法的性质
- 结合律
证明:
记 \(\mathbf{A}=(a_{i,j})_{m\times n},\mathbf{B}=(b_{i,j})_{n\times s},\mathbf{C}=(c_{i,j})_{s\times t}\),对于 \(1\le i\le m,1\le j\le t\),比较 \((\mathbf{A}\mathbf{B})\mathbf{C}\) 与 \(\mathbf{A}(\mathbf{B}\mathbf{C})\) 的 \((i,j)\) 元素。
一方面,\(\mathbf{A}\mathbf{B}\) 的第 \(i\) 行元素为:
\((\mathbf{A}\mathbf{B})\mathbf{C}\) 的 \((i,j)\) 元素为:
另一方面,\(\mathbf{B}\mathbf{C}\) 的第 \(j\) 列元素为:
\(\mathbf{A}(\mathbf{B}\mathbf{C})\) 的 \((i,j)\) 元素为:
二者是相等的,于是结合律得证。
- 分配律
证明:
与结合律类似,略。
注: 矩阵乘法不满足交换律与消去律。
矩阵快速幂与线性递推
利用矩阵乘法的结合律,我们可以使用快速幂的方法求一个矩阵 \(\mathbf{A}\) 的 \(m\) 次幂 \(\mathbf{A}^m\),进而可以用于优化常系数齐次线性递推。
基础矩阵优化递推
已知一个数列 \(a\),它满足 \(a_n=\begin{cases}1&n\in\{1,2,3\}\\a_{n-1}+a_{n-3}&n\ge 4\end{cases}\),求 \(a\) 数列的第 \(n\) 项。
sol:
把转移写成矩阵形式:
矩阵快速幂求系数矩阵的 \(n-3\) 次幂即可,复杂度 \(O(\log n)\)。
邻接矩阵的乘法
对一个有向图 \(G\),记其邻接矩阵为 \(A\),则 \(A^k\) 的 \((i,j)\) 元素为从 \(i\) 出发,走 \(k\) 步走到 \(j\) 的路径数。
如果只考虑可达性,此时矩阵中只有 \(0\) 和 \(1\),乘法变成与操作,加法变成或操作,使用 bitset 可以将矩阵乘法优化到 \(O(\frac{n^3}{\omega})\)。
注:除此之外,很多 dp 也可以用类似于常系数齐次线性递推的方式优化。
动态 dp
动态 dp,就是把状态转移方程改写为矩阵后用数据结构维护的算法。
这里的矩阵可以是常见的 \((+,\times)\) 矩阵,也可能是 \((\min/\max,+)\) 矩阵。
这里的 \((\max,+)\) 矩阵的矩阵乘法定义为:
矩阵 \(\mathbf{A}=(a_{i,j})_{m\times n},\mathbf{B}=(b_{i,j})_{n\times s}\),则 \(\mathbf{A}\mathbf{B}=(c_{i,j})_{m\times s}\),其中:
这里的 \((\max,+)\) 矩阵乘法和 \((+,\times)\) 矩阵乘法一样,都具有结合律,即 \((\mathbf{A}\mathbf{B})\mathbf{C}=\mathbf{A}(\mathbf{B}\mathbf{C})\)。
同样,在树形 dp 中,结合使用轻重链剖分等数据结构技巧,可以用动态 dp 的 \((\max,+)\) 矩阵快速维护树形 dp。
例题在后面。
例题
- 迷路
有向图有 \(n\) 个节点,节点从 \(1\) 至 \(n\) 编号,边有边权。windy 从节点 \(1\) 出发,他必须恰好在 \(t\) 时刻到达节点 \(n\)。
现在给出该有向图,你能告诉 windy 总共有多少种不同的路径吗?(注:\(2\le n\le 10\),\(1\le\) 边权 \(\le 9\))
sol:
拆边,若一条边 \(u\rightarrow v\) 的权值为 \(w\),那么新建点 \((x_1,x_2,\cdots,x_{w−1})\),连边 \(u\rightarrow x_1\rightarrow x_2\rightarrow\cdots\rightarrow x_{w−1}\rightarrow v\),边权均为 \(1\)。
对新图的邻接矩阵求 \(t\) 次幂即可。
矩阵的大小是新图的点数 \(N=8m=8n^2\) 级别的,复杂度 \(O(N^3\log t)\)。但是复杂度还可以更优。
考虑对每个点拆点,\((u,0)\rightarrow(u,1)\rightarrow(u,2)\rightarrow \cdots\rightarrow(u,8)\)。对于一条 \(u\rightarrow v\),边权为 \(w\) 的边,连边 \((u,w-1)\rightarrow(v,0)\)。
矩阵的大小是新图的点数 \(N=9n\) 级别的,复杂度 \(O(N^3\log t)\)。
- 超级跳马
现有一个 \(n\) 行 \(m\) 列的棋盘,一只马欲从棋盘的左上角跳到右下角。
每一步它向右跳奇数列,且跳到本行或相邻行,且跳越期间,马不能离开棋盘。试求跳法种数。
数据范围:\(n\le50,m\le 10^9\)
sol:
设 \(f_{i,j}\) 表示跳到 \((i,j)\) 的方案数。
考虑从哪一行转移过来,有方程:
发现 \(f_{i,j-2}=\sum\limits_{k=2}f_{i-1,j-(2k-1)}+f_{i,j-(2k-1)}+f_{i+1,j-(2k-1)}\),于是把方程转成线性递推的形式:
写成矩阵形式,以 \(n=3\) 为例:
做矩阵快速幂即可,复杂度 \(O(n^3\log m)\)。
- Placing Squares
给定一个长度为 \(n\) 的木板,木板上 \(n-1\) 个整数位置上有 \(m\) 个被标记。
现在你需要在木板上放置一些不相交正方形,正方形需要满足:边长为整数、底面需要紧贴木板、正方形不能超出木板、正方形要将所有的木板覆盖、标记点的位置不能是两个正方形的交界处。
一种合法的正方形放置方案的贡献为所有正方形面积之积,求出所有合法方案的贡献之和。
sol:
先不考虑有标记的情况。那么这个问题有一个巧妙的转化:
-
一排 \(n\) 个格子,需要用板子把他们分成若干段。
-
每段的格子里放有恰好两个不同颜色小球,方案数 \(a^2\)。
这个问题的方案数就是所有正方形面积之积的和。
考虑 dp,设 \(f_{i,j}\) 表示前 \(i\) 个格子里,最后一段没有被封口的格子里有 \(j\in[0,2]\) 个小球的方案数,有转移:
-
\(f_{i+1,0}=f_{i,0}+f_{i,2}\)(在 \(i\) 与 \(i+1\) 之间放隔板或不放隔板)。
-
\(f_{i+1,1}=2f_{i,0}+f_{i,1}+2f_{i,2}\)(放隔板可以从 \(f_{i,2}\) 转移过来,由于有两种颜色的球所以乘 \(2\);不放隔板可以从 \(f_{i,0},f_{i,1}\) 转移过来,同理 \(f_{i,0}\) 前的系数也需乘 \(2\))。
-
\(f_{i+1,2}=f_{i,0}+f_{i,1}+2f_{i,2}\)(放隔板可以从 \(f_{i,2}\) 转移过来,不放隔板可以从 \(f_{i,0},f_{i,1},f_{i,2}\) 转移过来;以上四种情况均只有一种放法,而 \(f_{i,2}\) 前系数的 \(2\) 是因为 \(f_{i,2}\) 出现了两次)。
于是可以写出矩阵形式:
现在考虑有标记的情况:按标记分段,每段中间矩阵快速幂,然后遇到标记特判一下转移。
特殊的转移:
-
\(f_{i+1,0}=f_{i,0}\)。
-
\(f_{i+1,1}=2f_{i,0}+f_{i,1}\)。
-
\(f_{i+1,2}=f_{i,0}+f_{i,1}+f_{i,2}\)。
矩阵形式:
于是解决了问题,复杂度 \(O(m\log n)\)。
- New Year and Old Subsequence
定义一个数字串是好的当且仅当:该串包含子序列 2017,且不包含子序列 2016。
给定长为 \(n\) 的数字串 \(t\),\(q\) 次询问,每次询问给出 \(l,r\),求把 \(t[l,r]\) 这个子串变成好的,最少要删除几个字符。
sol:
先考虑一个串怎么做,直接 dp:
设 \(f_{i,0/1/2/3/4}\) 表示 \(i\) 个数字的子序列中出现 \(\varnothing\)/2/20/201/2017 且不出现 2016 最少需要删去多少个字符,有转移:
-
\(f_{i,0}=f_{i-1,0}+[s_i=2]\)。
-
\(f_{i,1}=\min(f_{i-1,1}+[s_i=0],f_{i-1,0}[s_i=2])\)。
-
\(f_{i,2}=\min(f_{i-1,2}+[s_i=1],f_{i-1,1}[s_i=0])\)。
-
\(f_{i,3}=\min(f_{i-1,3}+[s_i=7\lor s_i=6],f_{i-1,2}[s_i=1])\)。
-
\(f_{i,4}=\min(f_{i-1,4}+[s_i=6],f_{i-1,3}[s_i=7])\)。
把它写成 \((\min,+)\) 矩阵,用线段树维护区间矩阵之积即可。
复杂度 \(O(q\log n)\)。

浙公网安备 33010602011771号