常系数齐次线性递推

前言

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

特征多项式

若有常数 λ \lambda λ,向量 v → \overrightarrow v v ,对于n阶矩阵A满足 λ v → = A v → \lambda\overrightarrow v=A\overrightarrow v λv =Av
那么称 λ \lambda λ为A的特征值, v → \overrightarrow v v 为A的特征向量
有一个定理,秩为k的矩阵有k组线性无关的特征向量
我们把式子变一下形
( A − λ I ) v → = 0 (A-\lambda I)\overrightarrow v=0 (AλI)v =0
I是单位矩阵
这个式子有解的充要条件为 d e t ( A − λ I ) = 0 det(A-\lambda I)=0 det(Aλ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) f(A)=i=1n(λiIA)
如果对于每个特征向量 v i → \overrightarrow {v_i} vi 都有 v i → f ( A ) = 0 \overrightarrow {v_i}f(A)=0 vi 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 vi (λiIA)=vi λiIvi 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} a1100...0a2010...0a3001...0..................an000...1hn1hn2hn3hn4...h0=hnhn1hn2hn3...h1
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(λ)=λa110...0a2λ1...0a30λ...0...............an100...1an00...λ
根据第一行展开 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} f(λ)=(λa1)A1,1+(a2)A1,2+(a3)A1.3...+(An)A1,n
其中 A i , j A_{i,j} Ai,j表示A的代数余子式
显然所有余子式都是下三角矩阵,行列式很容易求得
那么我们得到了 f ( λ ) = λ n − ∑ i = 1 n a i λ n − i f(\lambda)=\lambda^n-\sum_{i=1}^{n}ai\lambda^{n-i} f(λ)=λni=1naiλni
所谓特征多项式(刚好是特征根的形式的说)

如何计算

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

例题(bzoj4161)

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

#include 
#include 
#include 
#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 (n1) 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;
}

你可能感兴趣的:(学习小记,线性代数)