原问题
给定一个数列前k项,并给出其k阶递推关系
hn=∑ki=1aihn−i
,求
hn
。
矩阵快速幂
大家都会矩阵快速幂的方法。
构造一个转移矩阵
A
A=⎡⎣⎢⎢⎢⎢⎢⎢a110⋮0a201⋮0a300⋮0⋯⋯⋯⋱1ak00⋮0⎤⎦⎥⎥⎥⎥⎥⎥
用前k项构造初始矩阵,也是一个k维向量
H1
H1=⎛⎝⎜⎜⎜⎜⎜⎜hkhk−1hk−2⋮h1⎞⎠⎟⎟⎟⎟⎟⎟
即可得
An−1H1=Hn
。
时间复杂度
O(k3logn)
。
k如果比较大怎么办?我会卡常,jki玄学卡常,wys优化
扫描二维码关注公众号,回复:
2824051 查看本文章
多项式取模优化
前置知识
1.矩阵的特征值
对于矩阵
A
和一个n维向量
x
,如果有一个值
λ
满足
Ax=λx
,则我们称
λ
为矩阵
A
的特征值。
2.矩阵的特征多项式
简单的缩好像就是特征方程再移项?
我们把之前的那个方程移项得
(A−λE)x=0
,显然若x有非零解,那么需要满足
|A−λE|=∣∣∣∣∣∣∣∣∣a11−λa21a31⋮ak1a12a22−λa32⋮ak2a13a23a33−λ⋮ak3⋯⋯⋯⋱⋯a1ka2ka3k⋮akk−λ∣∣∣∣∣∣∣∣∣=0
这其实是一个一元k阶方程,即特征方程。我们记
fA(x)=|A−xE|
,称矩阵A的特征多项式。
3.Cayley-Hamilton定理
fA(A)=0
。具体的证明可以看widipedia,因为我也不会。
为了方便记忆,有一个著名的伪证:
fA(A)=|A−AE|=0
。
4.拉普拉斯展开
对于行列式A,我们定义它的关于第i行第j列的余子式
Mij
为原行列式删除第i行和第j列之后剩下的k-1阶行列式。
拉普拉斯展开是一个有关行列式的值的等式,按第i行展开得到如下等式
|A|=∑j=1k(−1)j−1aij|Mij|
类似的,我们也可以对第j列展开
|A|=∑i=1k(−1)iaij|Mij|
5.多项式取模
f(x)=g(x)p(x)+r(x)
它们满足
deg(r)<deg(g)<deg(f)
。
优化
我们知道如果给矩阵的某一行全部元素全部变为相反数,那么矩阵的行列式也会变成相反数,那么我们可以做这样一个操作,并记作
g
:
g(x)=(−1)kfA(x)=∣∣∣∣∣∣∣∣∣x−a1−10⋮0−a2x−1⋮0−a30x⋮0⋯⋯⋯⋱−1−ak000x∣∣∣∣∣∣∣∣∣
为了求
g(x)
的表达式,我们可以按照第一行对其进行拉普拉斯展开:
g(x)=xk−∑i=1kaixk−i
由于我们要求的东西就是
An
,那不妨构造一个这样的式子:
xn=g(x)p(x)+r(x)
令
x=A
则有
An=g(A)p(A)+r(A)
由之前的Cayley-Hamilton定理我们知道
g(A)=(−1)kfA(A)=0
。那么我们就得到了
An=r(A)
,而
deg(r)<k
。为了方便,我们不妨看作
deg(r)=k−1
。
那么我们怎么求
r(A)
呢?原来的取模板子显然不可取,因为n可能很大,数组都开不下。考虑用倍增,即
x2modg(x)=(x1modg(x))2modg(x),x4modg(x)=(x2modg(x))2modg(x)
考虑用快速幂实现,这需要做两个操作:
* 1.多项式乘法
* 暴力
O(k2)
* FFT
O(klogk)
* 2.多项式取模
* 暴力
O(k2)
,跳过中间的零项
O(kt)
* FFT
O(klogk)
,限制多,有时用不了?
至此,我们已经得到了
An=∑k−1i=0riAi
,再在两边乘上初始矩阵
H1
即得
Hn+1=∑i=0k−1riHi+1
由于
H
是一个n维向量,而且中间涉及到的数乘及加法的运算,对于每一行是独立的,直接把第k行上的运算提出来就得到
hn+1=∑i=0k−1rihi+1
时间复杂度常数较大的
O(k2logn)
,或者常数更大的
O(klogklogn)
,fft的话要注意精度问题,mod较大就可能有问题。
相关题目
看了这么久,然而貌似应用不多?
bzoj4161
hdu4914