常系数齐次线性递推

常系数齐次线性递推

要干啥

已知

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

(f[n])的值,(nle 10^9,kle 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]),那么最终我们的答案向量可以写成:

[egin{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))

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

原文地址:https://www.cnblogs.com/cjyyb/p/10152566.html