常系数齐次线性递推

版权声明:既然是蒟蒻写的文,那么各位大爷就将就着看吧~ https://blog.csdn.net/alan_cty/article/details/83065815

前言

上了高二学了数列,知道了如何给出递推求通项,也从数竞同学那里听来了高阶常系数齐次线性递推的通项求法。
那么OI上如何应用呢?
百度了一下发现自己在这一块的技能点为0,就决定学一学QwQ
线性代数渣没办法

特征多项式

若有常数 λ \lambda ,向量 v \overrightarrow v ,对于n阶矩阵A满足 λ v = A v \lambda\overrightarrow v=A\overrightarrow v
那么称 λ \lambda 为A的特征值, v \overrightarrow v 为A的特征向量
有一个定理,秩为k的矩阵有k组线性无关的特征向量
我们把式子变一下形
( A λ I ) v = 0 (A-\lambda I)\overrightarrow v=0
I是单位矩阵
这个式子有解的充要条件为 d e t ( A λ I ) = 0 det(A-\lambda I)=0
左边的东西显然是一个关于 λ \lambda 的n次多项式,称作A的特征多项式
这个多项式的n个根就是n组特征值了

Cayley-Hamilton定理

设矩阵A的特征多项式为f(x),那么f(A)=0
这里f(A)可以理解成把多项式里面的乘法换成矩阵乘法
证明:考虑写成 f ( A ) = i = 1 n ( λ i I A ) f(A)=\prod_{i=1}^{n}(\lambda_i I-A)
如果对于每个特征向量 v i \overrightarrow {v_i} 都有 v i f ( A ) = 0 \overrightarrow {v_i}f(A)=0 ,由于这些特征向量线性无关,所以有f(A)=0
考虑一个特征向量和其对应的特征值
v i ( λ i I A ) = v i λ i I v i A \overrightarrow {v_i}(\lambda_i I-A)=\overrightarrow {v_i}\lambda_i I-\overrightarrow {v_i}A
根据定义这个东西为0
Q.E.D
矩阵乘法不满足交换律?其实在这里满足,把式子拆一下就好了

求解常系数齐次线性递推转移矩阵的特征多项式

特征多项式可以直接差值求,但在我们的这个问题里可以不用
( a 1 a 2 a 3 . . . a n 1 0 0 . . . 0 0 1 0 . . . 0 0 0 1 . . . 0 . . . . . . . . . . . . . . . 0 0 0 . . . 1 ) ( h n 1 h n 2 h n 3 h n 4 . . . h 0 ) = ( h n h n 1 h n 2 h n 3 . . . h 1 ) \begin{pmatrix} a_1&a_2&a_3&...&a_n\\ 1&0&0&...&0\\ 0&1&0&...&0\\ 0&0&1&...&0\\ ...&...&...&...&...\\ 0&0&0&...&1 \end{pmatrix} \begin{pmatrix} h_{n-1}\\ h_{n-2}\\ h_{n-3}\\ h_{n-4}\\ ...\\ h_0 \end{pmatrix}= \begin{pmatrix} h_n\\ h_{n-1}\\ h_{n-2}\\ h_{n-3}\\ ... \\ h_1 \end{pmatrix}
f ( λ ) = ( λ a 1 a 2 a 3 . . . a n 1 a n 1 λ 0 . . . 0 0 0 1 λ . . . 0 0 . . . . . . . . . . . . . . . . . . 0 0 0 . . . 1 λ ) f(\lambda)=| \begin{pmatrix} \lambda-a1&-a2&-a3&...&-a_{n-1}&-an\\ -1&\lambda&0&...&0&0\\ 0&-1&\lambda&...&0&0\\ ...&...&...&...&...&...\\ 0&0&0&...&-1&\lambda \end{pmatrix} |
根据第一行展开 f ( λ ) = ( λ a 1 ) A 1 , 1 + ( a 2 ) A 1 , 2 + ( a 3 ) A 1.3 . . . + ( A n ) A 1 , n f(\lambda)=(\lambda-a_1)A_{1,1}+(-a2)A_{1,2}+(-a3)A_{1.3}...+(-An)A_{1,n}
其中 A i , j A_{i,j} 表示A的代数余子式
显然所有余子式都是下三角矩阵,行列式很容易求得
那么我们得到了 f ( λ ) = λ n i = 1 n a i λ n i f(\lambda)=\lambda^n-\sum_{i=1}^{n}ai\lambda^{n-i}
所谓特征多项式(刚好是特征根的形式的说)

如何计算

回到原问题,我们要求形如 H A m H*A^m 的式子
我们知道 f ( A ) = 0 f(A)=0 ,所以 A m = A m m o d    f ( A ) A^m=A^m \mod f(A)
做多项式取模我们得到了一个关于A的n-1次多项式,记为 i = 0 n 1 c i A i \sum_{i=0}^{n-1}c_iA^i
那么我们要求的就是 i = 0 n 1 c i A i H \sum_{i=0}^{n-1}c_iA^iH 的第m项
A i H = h i + n A^iH=h_{i+n} ,也就是 i = 0 k 1 c i h i + k \sum_{i=0}^{k-1}c_ih_{i+k}
那么我们先O(n^2)把 h n . . . h 2 n 1 h_n...h_{2*n-1} 计算出来就好了
多项式取模可以用NTT也可以直接暴力

例题(bzoj4161)

直接O(k^2 log k)求出 x n % f ( x ) x^n\%f(x)
注意特判k=1的情况(虽然数据没有)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

typedef long long ll;

const int N=4e3+5,Mo=1e9+7;

int n,k,a[N],h[N],f[N],g[N],b[N],an[N];

void mul(int *a,int *b,int *c) {
	fo(i,0,2*k-2) g[i]=0;
	fo(i,0,k-1) fo(j,0,k-1) (g[i+j]+=(ll)a[i]*b[j]%Mo)%=Mo;
	fd(i,2*k-2,k)
		fd(j,k-1,0) 
			(g[i-k+j]-=(ll)g[i]*f[j]%Mo)%=Mo;
	fo(i,0,k-1) c[i]=g[i];
}

int main() {
	scanf("%d%d",&n,&k);
	fo(i,1,k) scanf("%d",&a[i]);
	fo(i,0,k-1) scanf("%d",&h[i]);
	if (n<k) {printf("%d",(h[n]+Mo)%Mo);return 0;}
	fo(i,0,k-1) f[i]=-a[k-i];f[k]=1;
	if (k>1) b[1]=1;
	else b[0]=-f[0];
	an[0]=1;
	for(n-=k-1;n;n>>=1) {
		if (n&1) mul(an,b,an);
		mul(b,b,b);
	}
	fo(i,k,2*k-1)
		fo(j,1,k)
			(h[i]+=(ll)h[i-j]*a[j]%Mo)%=Mo;
	int ans=0;
	fo(i,0,k-1) (ans+=(ll)an[i]*h[i+k-1]%Mo)%=Mo;
	printf("%d\n",(ans+Mo)%Mo);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/alan_cty/article/details/83065815