快速幂法求解线性递推关系的高效矩阵算法
题目描述
给定一个k阶线性齐次递推关系,形如:
\[a_{n} = c_1 a_{n-1} + c_2 a_{n-2} + \dots + c_k a_{n-k}, \quad n \ge k \]
已知初始值 \(a_0, a_1, \dots, a_{k-1}\) 和系数 \(c_1, c_2, \dots, c_k\),要求高效计算第n项 \(a_n\),其中n通常很大(例如 \(n = 10^{18}\))。直接递推需要 \(O(n)\) 时间,不可接受。本算法通过构造矩阵并利用矩阵快速幂,将时间复杂度降为 \(O(k^3 \log n)\)。
逐步讲解
- 问题转化:构造伴随矩阵
将递推式转化为矩阵形式。定义状态向量:
\[ \mathbf{v}_n = \begin{bmatrix} a_{n} \\ a_{n-1} \\ \vdots \\ a_{n-k+1} \end{bmatrix} \in \mathbb{R}^k \]
根据递推关系,可写出:
\[ \mathbf{v}_n = \begin{bmatrix} c_1 & c_2 & \cdots & c_{k-1} & c_k \\ 1 & 0 & \cdots & 0 & 0 \\ 0 & 1 & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & 1 & 0 \end{bmatrix} \mathbf{v}_{n-1} = M \mathbf{v}_{n-1} \]
矩阵 \(M\) 称为伴随矩阵(companion matrix),其第一行为递推系数,次对角线下方全为1,其余为0。
- 递推的矩阵表示
反复应用上述关系,得到:
\[ \mathbf{v}_n = M \mathbf{v}_{n-1} = M^2 \mathbf{v}_{n-2} = \dots = M^{n-k+1} \mathbf{v}_{k-1} \]
其中初始向量 \(\mathbf{v}_{k-1} = [a_{k-1}, a_{k-2}, \dots, a_0]^T\)。
目标 \(a_n\) 是 \(\mathbf{v}_n\) 的第一个分量,即 \(a_n = \mathbf{e}_1^T M^{n-k+1} \mathbf{v}_{k-1}\),其中 \(\mathbf{e}_1 = [1,0,\dots,0]^T\)。
-
核心:矩阵快速幂
计算 \(M^{n-k+1}\) 若直接连乘需 \(O(n)\) 次矩阵乘法。利用快速幂思想(如计算标量 \(a^b\) 的二分幂):- 将指数 \(m = n-k+1\) 二进制分解:\(m = \sum_{i} 2^{b_i}\)。
- 预处理 \(M^{2^0}, M^{2^1}, M^{2^2}, \dots\) 通过反复平方:\(M^{2^{i+1}} = (M^{2^i})^2\)。
- 将对应的幂次矩阵相乘:\(M^m = \prod_{i} M^{2^{b_i}}\)。
每次矩阵乘法(\(k \times k\) 矩阵)需 \(O(k^3)\) 时间,共有 \(O(\log n)\) 次乘法,总复杂度 \(O(k^3 \log n)\)。
-
算法步骤
(1) 输入:阶数k,系数数组 \(c[1..k]\),初始值数组 \(a[0..k-1]\),目标索引n。
(2) 若 \(n < k\),直接返回 \(a[n]\)。
(3) 构造 \(k \times k\) 伴随矩阵 \(M\):
- 第一行:\(M[1][j] = c_j\)(\(j=1..k\))
- 第i行(\(i=2..k\)):\(M[i][i-1] = 1\),其余为0。
(4) 计算 \(m = n - k + 1\),用快速幂计算 \(P = M^m\)。
(5) 构造初始向量 \(\mathbf{v} = [a_{k-1}, a_{k-2}, \dots, a_0]^T\)。
(6) 计算 \(\mathbf{u} = P \mathbf{v}\)(矩阵乘向量)。
(7) 输出 \(a_n = \mathbf{u}[1]\)(向量的第一个分量)。 -
举例说明(斐波那契数列)
递推:\(F_n = F_{n-1} + F_{n-2}\),初始 \(F_0=0, F_1=1\)。- 阶数 \(k=2\),系数 \(c_1=1, c_2=1\),初始向量 \(\mathbf{v}_1 = [F_1, F_0]^T = [1,0]^T\)。
- 伴随矩阵 \(M = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\)。
- 计算 \(F_{10}\):\(m = 10-2+1 = 9\)。
\(9 = 8+1\),平方过程:
\(M^1 = M\),
\(M^2 = M \cdot M = \begin{bmatrix} 2 & 1 \\ 1 & 1 \end{bmatrix}\),
\(M^4 = (M^2)^2 = \begin{bmatrix} 5 & 3 \\ 3 & 2 \end{bmatrix}\),
\(M^8 = (M^4)^2 = \begin{bmatrix} 34 & 21 \\ 21 & 13 \end{bmatrix}\),
则 \(M^9 = M^8 \cdot M^1 = \begin{bmatrix} 55 & 34 \\ 34 & 21 \end{bmatrix}\)。 - \(\mathbf{u} = M^9 \mathbf{v}_1 = [55, 34]^T\),故 \(F_{10} = 55\),正确。
-
优化与扩展
- 若只需单项 \(a_n\),可只计算 \(M^m\) 的第一行(用快速幂结合线性递推性质,可优化到 \(O(k^2 \log n)\))。
- 可推广到非齐次递推(增加常数项)或带前k项线性组合的递推。
- 在模算术下(如大数取模),矩阵元素在模意义下运算,适合大指数问题。
总结
本算法将线性递推转化为矩阵幂问题,利用快速幂大幅降低计算量,是处理大索引递推问题的标准技术,广泛应用于动态规划加速、多项式计算、组合计数等领域。