1.定长路径统计

给出一个\(n\)个点\(m\)条边的有向图,每次给出三个整数\(u,v,k\),求有多少条从\(u\)到\(v\)的路径长度为\(k\)(不一定为简单路径)

我们用邻接矩阵\(G\)存储这个图,\(G_{u,v}\)表示从\(u\)到\(v\)的边数

令\(F_k\)为长度为\(k\)的路径条数构成的矩阵,显然有:


\[F_{k_{i,j}}=\sum\limits_{k=1}^{n} F_{k-1_{i,k}}\times G_{k,j}\]


我们将其看作是两个矩阵相乘:


\[F_k=F_{k-1}\times G\]


那么显然有:


\[F_k=G^{k}\]


矩阵快速幂即可

2.定长路径统计*

给出一个\(n\)个点\(m\)条边的有向图,每次给出三个整数\(u,v,k\),求有多少条从\(u\)到\(v\)的路径长度小于等于\(k\)(不一定为简单路径)

我们把每个点加一条连向自己的边权为\(1\)的边,跑矩阵快速幂即可

3.「LibreOJ 6208」树上询问

给出一棵有\(n\)个节点的树,根节点为\(1\)号节点每个节点有两个值\(k,t\),初始均为\(0\)
每次进行如下\(3\)种操作之一:
\(1.\operatorname{Add}(x,d)\):将\(x\)到根节点路径上每个点的\(k_i\leftarrow k_i+d\)
\(2.\operatorname{Mul}(x,d)\):将\(x\)到根节点路径上每个点的\(t_i\leftarrow t_i+d\times k_i\)
\(3.\operatorname{Query}(x)\):求\(t_x\)
\(1\le n,m\le 10^5,-10\le d\le 10\)

直接树剖确实可以做,但是比较麻烦,我们用矩阵来刻画每个操作:

\(\operatorname{Add}\):


\[\begin{bmatrix}t_i &k_i&1 \end{bmatrix}\begin{bmatrix}1&0&0\\0&1&0\\0&d&1\end{bmatrix}=\begin{bmatrix}t_i&k_i+d&1\end{bmatrix}\]


\(\operatorname{Mul}\):


\[\begin{bmatrix}t_i &k_i&1 \end{bmatrix}\begin{bmatrix}1&0&0\\d&1&0\\0&0&1\end{bmatrix}=\begin{bmatrix}t_i+d\times k_i&k_i&1\end{bmatrix}\]


然后树剖维护即可

4.[TJOI2019]甲苯先生的字符串

给出一个仅有小写字母字符串\(S_1\),求满足如下条件的字符串\(S_2\)有多少种:
\(1.S_2\)长度为\(n\)
\(2.S_2\)仅由小写字母构成
\(3.S_1\)中长度为\(2\)的任意连续子串在\(S_2\)中不能出现
\(1\le n\le 10^{15}\)

我们将小写字母映射为数字,即\(a=1,b=2\dots z=26\)

令\(dp_{i,j}\)为长度为\(i\)且当前字符为\(j\)的合法字符串数量,显然有:


\[dp_{i,j}=\sum\limits_{k=1}^{26}dp_{i-1,k}[kj\not\in S_1]\]


我们预处理出后面那个东西,令它为\(w\),那么就有:


\[dp_{i,j}=\sum\limits_{k=1}^{26}dp_{i-1,k}\times w_{k,j}\]


\(n\)很大,暴力\(dp\)会炸掉,发现上面的转移方程是矩阵乘法的形式,可以用矩阵优化:

原矩阵:


\[\begin{bmatrix}dp_{i,1}&dp_{i,2}&\cdots&dp_{i,26}\end{bmatrix}\]


​base​​矩阵:


\[\begin{bmatrix}w_{1,1}&w_{1,2}&\cdots&w_{1,26}\\w_{2,1}&w_{2,2}&\cdots&w_{2,26}\\\vdots&\vdots&\ddots&\vdots\\w_{26,1}&w_{26,2}&\cdots&w_{26,26}\end{bmatrix}\]


5.[SHOI2013]超级跳马

现有一个 \(n\) 行 \(m\) 列的棋盘,一只马欲从棋盘的左上角跳到右下角。每一步它向右跳奇数列,且跳到本行或相邻行。跳跃期间,马不能离开棋盘。例如,当 \(n=3,m=10\) 时,下图是一种可行的跳法。
矩阵乘法例题讲解_矩阵快速幂
求总方案数。
\(1\le n\le 50,2\le m\le 10^9\)

设\(dp_{i,j}\)为跳到\((i,j)\)的方案数,显然当只往右跳\(1\)格时有:


\[dp_{i,j}=dp_{i-1,j-1}+dp_{i,j-1}+dp_{i+1,j-1}\]


考虑到如果能一次跳到\((i,j)\),那么肯定也可以一次跳到\((i,j-2)\),所以转移方程即为:


\[dp_{i,j}=dp_{i-1,j-1}+dp_{i,j-1}+dp_{i+1,j-1}+dp_{i,j-2}\]


直接\(dp\)发现\(O(nm)\)的复杂度接受不了,考虑矩阵优化(以\(n=3\)为例):

原矩阵:


\[\begin{bmatrix}dp_{1,j}&dp_{2,j}&dp_{3,j}&dp_{1,j-1}&dp_{2,j-1}&dp_{3,j-1}\end{bmatrix}\]


​base​​矩阵:


\[\begin{bmatrix}1&1&0&1&0&0\\1&1&1&0&1&0\\0&1&1&0&0&1\\1&0&0&0&0&0\\0&1&0&0&0&0\\0&0&1&0&0&0\end{bmatrix}\]


注意到\(n\)非常小,故以上做法可以通过