常系数齐次线性递推
要干啥
已知
[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))
似乎这篇文章里面有些细节上的东西写得不是很好,意会一下就好了。