常系数齐次线性递推

常系数齐次线性递推

要干啥

已知

\[f[n]=\sum_{i=1}^k C_if[n-i] \]

\(f[n]\)的值,\(n\le 10^9,k\le 20000\),答案取模。

暴力做法

如果复杂度\(O(nk)\)允许的话,显然是可以直接\(dp\)转移的。
\(k\)很小的时候,转移写成矩阵形式,假设转移矩阵为\(M\),可以得到:\(\displaystyle f[n]=f[0]*M^n\),这里的\(f\)是向量的形式。
复杂度为\(O(k^3logn)\)

所以到底要怎么做

显然我们已知矩乘的时候是一个\(n\)维向量乘上转移矩阵得到了一个\(n\)维向量。
考虑这个转移的特征方程:

\[x^k=\sum_{i=1}^k C_ix^{k-i} \]

把它移项之后我们定义为特征多项式\(C(x)\)

\[C(x)=x^k-\sum_{i=1}^k C_ix^{k-i} \]

根据\(Cayley–Hamilton\)定理,得到\(C(M)=0\),即把\(x\)替换为转移矩阵\(M\),最终的结果是一个零矩阵。
而我们要求的就是\(M^n\),因此,我们只需要知道\(M^n\ mod \ C(M)\)的结果就好了。
求解这个过程可以类似快速幂的倍增求解,复杂度是两个\(log\)
假设最终求解出来的余数多项式为

\[G(x)=\sum_{i=0}^{k-1}g_ix^i \]

假设我们中间的向量为\(A[i]\),那么最终我们的答案向量可以写成:

\[\begin{aligned} A[0]G(M)&=A[0]\sum_{i=0}^{k-1}g_iM^i\\ A[0]G(M)&=\sum_{i=0}^{k-1}g_i(A[0]M^i)\\ A[0]G(M)&=\sum_{i=0}^{k-1}g_iA[i] \end{aligned}\]

而事实上我们要求的并不是最终的向量\(A[n]\),而只有向量\(A[n]\)的最后一项。
因此:

\[f[n]=\sum_{i=0}^{k-1}g_if[i] \]

那么这样一来我们把矩阵的转移变成了简单的数之间的转移。
时间复杂度为\(O(klogklogn)\)

似乎这篇文章里面有些细节上的东西写得不是很好,意会一下就好了。

posted @ 2018-12-20 21:29  小蒟蒻yyb  阅读(1248)  评论(2编辑  收藏  举报