「学习笔记」常系数齐次线性递推

前置知识

矩阵的运算

矩阵加法

只有当两个行数、列数分别相等的矩阵(同型矩阵)相加,加法运算才有意义。

下面举例说明:

\[\left[\begin{array}{ll} {1} & {2} \\ {3} & {4} \end{array}\right]+\left[\begin{array}{ll} {1} & {3} \\ {2} & {4} \end{array}\right]=\left[\begin{array}{ll} {2} & {5} \\ {5} & {8} \end{array}\right] \]

可以理解为相同的位置加起来,就变成了答案矩阵。

其中,加法满足这些特点:

  • 交换律:\(A+B=B+A\)
  • 结合律:\((A+B)+C=A+(B+C)\)

矩阵乘法

与数的乘法

所有矩阵中的数全部乘以这个数即为结果,举例:

\[\left[\begin{array}{ccc} {1} & {-1} & {3} \\ {2} & {6} & {-5} \end{array}\right] \times 4=\left[\begin{array}{ccc} {4} & {-4} & {12} \\ {8} & {24} & {-20} \end{array}\right] \]

满足特性:

  • 结合律:\((ab)A=a(bA),(a+b)A=aA+bA\)
  • 分配律:\(a(A+B)=aA+aB\)

与矩阵的乘法

先上例子:

\[\left[\begin{array}{lll} {1} & {2} & {3} \\ {4} & {5} & {6} \end{array}\right] \times\left[\begin{array}{cc} {10} & {5} \\ {8} & {2} \\ {15} & {3} \end{array}\right]=\left[\begin{array}{cc} {71} & {18} \\ {170} & {48} \end{array}\right] \]

即,设 \(A=(a_{ij})_{m\times s},B=(b_{ij})_{s\times n}\) ,那么 \(A\times B=C\) 中,\(C=(c_{ij})_{m\times n}\)

必须保证 \(A\) 的列与 \(B\) 的行相同,且不满足交换律。

但满足结合律

向量的特殊说明

这里我们使用的向量是 \(k\) 阶向量,不与一般的向量相同。

即这个向量有 \(k\) 个元素。

问题引入

给出一个数列 \(h\) 若满足满足

\[h_i=\sum_{j=1}^kh_{i-j}a_j \]

那么我们称其满足 \(k\) 阶齐次线性递推关系。

对于 \(h\) 的前 \(k\) 个元素由题目给定。

现要求 \(h_n\) 的值?

原问题:Shlw loves matrixI

如果 \(\text{BZOJ}\) 炸了,请看下面 BZOJ 太老了...

问题与上面一样,

一般方法

对于这样的问题,我们可以有一些比较简单的想法。

暴力递推

如果我们直接使用暴力将式子推到第 \(n\) 项,其时间复杂度大概是 \(\mathcal O(nk)\)

矩阵快速幂

对于这样的一个题,我们可以很巧妙地构造初始矩阵:

\[A= \begin{bmatrix} h_1&h_2&h_3&\ldots&h_{k-1}&h_k \end{bmatrix} \]

而加速矩阵即为

\[B= \begin{bmatrix} 0&0&\cdots&0&a_1 \\ 1&0&\cdots&0&a_2 \\ 0&1&\cdots&\vdots&a_3 \\ \vdots&\vdots&\ddots&0&\vdots \\ 0&0&0&1&a_k \end{bmatrix} \]

\(B\) 的左上——右下对角线往下移一个单位,其上面全部都是 \(1\) ,最后一列顺次从上往下为 \(a_1,a_2,a_3,\ldots a_k\)

那么,时间复杂度大概为 \(\mathcal O(k^3\log n)\) ,其中 \(\mathcal O(k^3)\) 为矩阵乘法的时间复杂度,而 \(\mathcal O(\log n)\) 是快速幂的时间复杂度。

对于矩阵快速幂的一些优化

对于我们之前的那些方法,方法一似乎较难优化,因而我们从矩阵快速幂的优化入手,想办法降低其复杂度 \(\mathcal O(k^3\log n)\)

特征值与特征向量

我们知道一个矩阵乘一个列向量仍然是一个列向量。

若对于 \(k\) 阶矩阵 \(A\) ,有常数 \(\lambda\) 与列向量 \(\overrightarrow v\) 满足

\[A\overrightarrow v=\lambda \overrightarrow v \]

那么我们称 \(\lambda\) 为特征值, \(\overrightarrow v\) 为特征向量。

优化内容

特征值与特征向量的定义,我们可以得到上面的那个等式,即

\[A\overrightarrow v=\lambda \overrightarrow v \]

令我们的 \(\overrightarrow v\) 为初始矩阵,而 \(A\) 为加速矩阵,而现在我们要找 \(\lambda\) 的值。

考虑将其展开,可得

\[\begin{bmatrix} a_1&a_2&a_3&\cdots&a_k \\ 0&0&0&\cdots&1 \\ 0&0&\cdots&1&0 \\ &&\vdots \\ 0&1&0&\ldots&0 \end{bmatrix} \times \begin{bmatrix} h_k \\ h_{k-1} \\ h_{k-2} \\ \vdots \\ h_1 \end{bmatrix} = \begin{bmatrix} h_{k+1} \\ h_{k} \\ h_{k} \\ \vdots \\ h_2 \end{bmatrix} =\lambda\overrightarrow v = \begin{bmatrix} \lambda h_{k} \\ \lambda h_{k-1} \\ \lambda h_{k-2} \\ \vdots \\ \lambda h_1 \end{bmatrix} \]

注意到上面的式子中的第三个矩阵和第四个矩阵的等量关系,发现

\[h_i=\lambda h_{i-1}=\lambda^2h_{i-2}=\lambda^3h_{i-3}=\cdots=\lambda^{i-1}h_1 \]

而根据定义,我们又有

\[h_{k+1}=a_1h_k+a_2h_{k-1}+\cdots+a_kh_1 \]

将所有的 \(h_i\) 全部换成 \(h_1\) ,可以得到

\[\lambda^kh_1=a_1\lambda^{k-1}h_1+a_2\lambda^{k-2}h_1+\cdots+a_k\lambda^0h_1 \]

那么,我们可以将 \(h_1\) 全部消掉,得到一个关于 \(\lambda^k\) 的等式,即

\[\lambda^k=a_1\lambda^{k-1}+a_2\lambda^{k-2}+\cdots +a_k \]

移项,可得

\[\lambda^k-a_1\lambda^{k-1}-a_2\lambda^{k-2}-\cdots -a_k=0 \]

考虑将 \(\lambda\) 换成关于 \(x\) 的方程,得原式为

\[x^k-a_1x^{k-1}-a_2x^{k-2}-\cdots-a_k=0 \]

我们令 \(f(x)=x^k-a_1x^{k-1}-a_2x^{k-2}-\cdots-a_k\)

下面有关于多项式操作中的除法/取模操作,如果有不会的,请看 多项式的蛇皮操作

现在我们求

\[x^n=f(x)g(x)+r(x) \]

上式中的 \(g(x),r(x)\) ,如果使用多项式的操作,似乎是很好求的,时间复杂度为 \(\mathcal O(k\log k)\)

但是,我们求这个东西有什么用呢?

考虑将 \(x\) 替换为矩阵 \(A\) ,那么有 \(f(x)=f(A)=O\) ,其中 \(O\)\(0\) 矩阵。

但是为什么 \(f(A)=O\)

这里,Hamilton-Cayley定理说明了这个问题,其内容如下:

对于矩阵 \(A\) 的特征多项式 \(f(x)\) ,满足 \(f(A)=0\)

证明看这里(百度百科)

说不定哪天我也会给出自己的证明啊...

如果你还是看不懂,就把它当成一个结论记下来。(作者太菜,只能这样做了)

继续说明,我们有了

\[A^n=f(A)g(A)+r(A) \]

因为 \(f(A)=O\) ,那么就有

\[A^n=r(A) \]

而我们通过多项式的操作能够得到 \(r(A)\) 的每一个系数的值。

而如果我们直接这样求的话,其时间复杂度为 \(\mathcal O(k^4)\)

但是我们看看我们要求的是 \(A^n\overrightarrow v\) 的每一项,考虑将其等价变换为求 \(r(A)\times \overrightarrow v\)

而由于 \(r(x)\) 的本质是一个多项式,那么它可以写成

\[r(A)=\sum_{i=0}^{k-1}c_iA^i \]

其中 \(c_i\) 是每一项的系数,那么 \(r(A)\overrightarrow v\) 就可以写为

\[r(A)\overrightarrow v=\sum_{i=0}^{k-1}c_iA^i\overrightarrow v \]

\(A^i\overrightarrow v\)=\(A\times (A^{i-1}\overrightarrow v)\) (满足结合律)

\(A^{i-1}\overrightarrow v\) 是一个向量,而向量乘一个矩阵时间复杂度是 \(\mathcal O(k^2)\) ,因为我们要求 \(k\) 个这样的式子,所以时间复杂度为 \(\mathcal O(k^3)\)

但是,还可以继续优化。

由于定义,我们知道 \(\overrightarrow v\)\(h_1,h_2,h_3\cdots h_{k-1},h_k\) 组成,且顺序已知。

\(A\times \overrightarrow v\)\(h_2,h_3,h_4\cdots h_k,h_{k+1}\)

那么,更广泛的推论为

\(A^i\times \overrightarrow v\)\(h_{i+1},h_{i+2}\cdots h_{i+k}\) 组成。

而我们最多只会求到 \(A^{k-1}\overrightarrow v\) ,即我们只会用到前 \(2k\)\(h\) 中的元素。

考虑将其暴力预处理出来,时间复杂度 \(\mathcal O(k^2)\) ,然后我们用 \(\mathcal O(k)\) 的时间即可处理出 \(A^i\times \overrightarrow v\) ,而我们要计算 \(k\) 个这样的多项式,最终时间复杂度为 \(\mathcal O(k^2)\)

但是时间复杂度真的是 \(\mathcal O(k^2)\) 吗?

不对的。

问题出在哪里,在于多项式除法的 \(x^n\) 取模 \(f(x)\) 的时候,这个 \(x^n\) 真的可以 \(\mathcal O(1)\) 地表示?

呵呵,此问题中 \(n\le 10^9\) ,存是存不下的。

所以我们只能倍增计算 \(x^n\) ,并且在一边倍增的时候取模 \(f(x)\) 即可,所以此处时间复杂度为 \(\mathcal O(k\log k\log n)\)

因而,总的时间复杂度为 \(\mathcal O(max\{k\log k\log n,k^2\})\)

总结算法步骤

  1. 处理出 \(f(x)\) ,时间复杂度 \(\mathcal O(k)\)
  2. 用快速幂求出 \(r(x)\) ,时间复杂度 \(\mathcal O(k\log k\log n)\)
  3. 预处理前 \(2k\)\(h\) ,时间复杂度 \(\mathcal O(k^2)\)
  4. 循环从 \(1\)\(k\) ,每次计算 \(c_iA^i\overrightarrow v\) ,用 \(\mathcal O(k)\) 的时间填 \(A^i\overrightarrow v\) 。总的复杂度 \(\mathcal O(k^2)\) ,此刻得到答案向量;
  5. 算法结束;

这就是常系数齐次线性递推的主要优化步骤...

代码

例题:Shlw loves matrixI

代码待补...


posted @ 2020-01-03 17:32  南枙向暖  阅读(544)  评论(1编辑  收藏  举报