矩阵乘法递推加速

警告,本文KaTex排版较多,请耐心等待页面加载完成再浏览。

如果有不想看的章节,请查看左侧 TOC 跳过。

0x00 什么是矩阵乘法

这是一个 \rm 2\times 3 的矩阵。

\rm A =\begin{bmatrix}a_{1,1}&a_{1,2}&a_{1,3} \cr a_{2,1}&a_{2,2}&a_{2,3}\end{bmatrix}

这是另一个 \rm 3\times 4 的矩阵。

\rm B =
\begin{bmatrix}
b_{1,1}&b_{1,2}&b_{1,3}&b_{1,4} \\
b_{2,1}&b_{2,2}&b_{2,3}&b_{2,4} \\
b_{3,1}&b_{3,2}&b_{3,3}&b_{3,4}
\end{bmatrix}

矩阵乘法的定义是,对于两个矩阵 \rm m \times p 的矩阵 A\rm p \times n 的矩阵 B,令矩阵 C = A\times B,则矩阵 C 中的第 ij 列的元素可以表示为:

C_{ij} = \sum\limits_{k = 1}^{p} a_{ik}\times b_{kj}

最后乘出来的矩阵是一个 \rm m \times n 的矩阵。

用稍微通俗一点的语言说,就是对于矩阵 C 的第 ij 列的元素值就是 A 矩阵第 i 行的元素和 B 矩阵第 j 列元素一一对应相乘的和。

如果你看不明白,那我就以矩阵 C \rm(2 \times 4) 的一个元素(c_{1,2})举个例子。
长公式不想打了啊啊啊

c_{1,2} = \sum\limits_{k = 1}^{p} a_{1,k}\times b_{k,2} = a_{1,1}\times b_{1,2} + a_{1,2}\times b_{2,2} + a_{1,3}\times b_{3,2}

好,现在你知道什么是矩阵乘法了。尝试一下 Hydro H1005.【模板】矩阵乘法

0x01 矩阵乘法和递推式之间的关系

先来看一道题:洛谷 P1962 斐波那契数列

这个东西不就是暴力循环就能拿分的题吗?

如果你是这么想的,那么就去逝逝罢,\sf\color{#fadb14} 60\space \color{white}\colorbox{#e74c3c}{Unaccpted}

1\le n<2^{63} 的范围不卡死你才怪。

接下来的思路有点奇妙。

记斐波那契数列第 n 项为 F_n
我们假定一个矩阵:

\begin{bmatrix}
F_n&F_{n – 1}
\end{bmatrix}

根据斐波那契数列的递推式,F_n = F_{n – 1} + F_{n – 2}

我们希望有一个矩阵 \rm base,达到如下效果:

\begin{bmatrix}
F_n&F_{n – 1}
\end{bmatrix} =
\begin{bmatrix}
F_{n – 1}&F_{n – 2}
\end{bmatrix}
\times \rm base

此时 \rm base =
\begin{bmatrix}
1&1 \cr
1&0
\end{bmatrix}

因此,只需要把 \rm base 推出来就可以了。

又由于矩阵乘法有结合律(在此不做证明),故可以将 F_n 表示如下:

\begin{aligned}
\begin{bmatrix}
F_n&F_{n – 1}
\end{bmatrix} &=
\begin{bmatrix}
F_{n – 1}&F_{n – 2}
\end{bmatrix}\times \rm base\cr
&= \begin{bmatrix}
F_{n – 2}&F_{n – 3}
\end{bmatrix}
\times\rm base \times\rm base\cr &=\cdots\cr&=
\begin{bmatrix}
F_1&F_2
\end{bmatrix}
\times \rm base^{n – 1}\cr &=
\begin{bmatrix}
1&1
\end{bmatrix}
\times\rm base^{n – 1}
\end{aligned}

矩阵/递推式练习

做几道练习题感受一下:(递推式转矩阵)

F_n = 3F_{n-1} + 2F_{n-2}

答案

\begin{bmatrix}
F_n&F_{n – 1}
\end{bmatrix} = \begin{bmatrix}
F_{n – 1}&F_{n – 2}
\end{bmatrix}
\times\begin{bmatrix}
3&1 \cr
2&0
\end{bmatrix}


F_n = 15F_{n-1} – 2F_{n-2}

答案

\begin{bmatrix}
F_n&F_{n – 1}
\end{bmatrix} =\begin{bmatrix}
F_{n – 1}&F_{n – 2}
\end{bmatrix} \times
\begin{bmatrix}
15&1 \cr
-2&0
\end{bmatrix}


F_n = 3F_{n-1} + 2F_{n-2} + F_{n-3}

答案

\begin{bmatrix}
F_n&F_{n – 1}&F_{n-2}
\end{bmatrix} = \begin{bmatrix}
F_{n – 1}&F_{n – 2}&F_{n-3}
\end{bmatrix} \times \begin{bmatrix}
3&1&0 \cr
2&0&1 \cr
1&0&0
\end{bmatrix}


F_n = 3F_{n-1} + 2F_{n-2} + F_{n-3}

答案

\begin{bmatrix}
F_n&F_{n – 1}&F_{n-2}
\end{bmatrix} =
\begin{bmatrix}
F_{n – 1}&F_{n – 2}&F_{n-3}
\end{bmatrix} \times \begin{bmatrix}
3&1&0 \cr
2&0&1 \cr
1&0&0
\end{bmatrix}


F_n = 3F_{n-1} + 2F_{n-2} + 114514

答案

\begin{bmatrix}
F_n&F_{n – 1}&114514
\end{bmatrix} = \begin{bmatrix}
F_{n – 1}&F_{n – 2}&114514
\end{bmatrix} \times
\begin{bmatrix}
3&1&0 \cr
2&0&0 \cr
1&0&1
\end{bmatrix}


还可以将多个递推式合成一个矩阵。

F_n = F_{n-1} + F_{n-2}

S_n = S_{n-1} + F_n

答案

S_n = S_{n-1} + F_n = S_{n-1} + F_{n-1} + F_{n-2}

\begin{bmatrix}
F_n&F_{n – 1}&S_n
\end{bmatrix} = \begin{bmatrix}
F_{n – 1}&F_{n – 2}&S_{n-1}
\end{bmatrix} \times
\begin{bmatrix}
3&1&1 \cr
2&0&1 \cr
1&0&1
\end{bmatrix}

0x03 矩阵快速幂

现在我们已经推出了 \begin{bmatrix}
F_n&F_{n – 1}
\end{bmatrix} = \begin{bmatrix}
1&1
\end{bmatrix} \times base^{n – 1}

这么做的时间复杂度还是 \rm O(n)(甚至更高),因此我们需要特殊手段进行优化。

这时候,我们就可以搬出矩阵快速幂了。矩阵快速幂与整数快速幂思路基本相同,唯一的不同就是将整数换成了矩阵。

模板题:洛谷 P3390 【模板】矩阵快速幂

建议封装一下矩阵结构体/类,这样写起来方便一点。注意取模。

总体时间复杂度:\rm O(\log n)

0x04 练习题

题目链接 名称
洛谷 P1962 斐波那契数列
洛谷 P1349 广义斐波那契数列
洛谷 P5789 [TJOI2017]可乐(数据加强版)
洛谷 P1707 刷题比赛
洛谷 P1397 [NOI2013] 矩阵游戏
洛谷 P2151 [SDOI2009] HH去散步
洛谷 P3216 [HNOI2011]数学作业
洛谷 P4159 [SCOI2009] 迷路

以及模板题。