关于矩阵加速数列递推:
给定一个递推数列 (f[i] = a_1*f[i-1] + a_2*f[i-2] … a_k*f[i-k]) ,我们普通计算的话肯定是逐个计算,复杂度较大。
我们可以用矩阵表示:
[ left[
egin{matrix}
f[i] \
f[i-1] \
… \
f[i-k]
end{matrix}
ight]
]
为了递推出 (f[n]) ,我们需要找到一个系数矩阵 (A) 使得:
[ left[
egin{matrix}
f[i] \
f[i-1] \
… \
f[i-k]
end{matrix}
ight]
=
A imes
left[
egin{matrix}
f[i-1] \
f[i-2] \
… \
f[i-k-1]
end{matrix}
ight]
]
就可以这样计算:
[ left[
egin{matrix}
f[n+k] \
f[n+k-1] \
… \
f[n]
end{matrix}
ight]
=
A^{n-1} imes
left[
egin{matrix}
f[k] \
f[k-1] \
… \
f[1]
end{matrix}
ight]
]
通过矩阵快速幂来计算 (A^n) 可以减小复杂度,问题是如何找到一个 (A) 矩阵
容易发现,(A)矩阵可以这样构造:
[ left[
egin{matrix}
a_1 & a_2 & … & a_k-1 & a_k \
1 & 0 & … & 0 & 0 \
0 & 1 & … & 0 & 0 \
… & … & … & … & … \
0 & 0 & … & 1 & 0
end{matrix}
ight]
]
即第一行为系数,从 (A_{2,1}) 开始的一条斜线为 (1), 其余为 (0),这样构造可以保证 (f[i]) 被计算出来了,而其余的元素都继承了上一个矩阵的值。
至此,我们可以愉快地用矩阵加速递推数列了。