常系数齐次线性递推优化矩阵快速幂-bzoj4161-4944

文章目录

      • 常系数齐次线性递推式
      • 特征值&特征向量&特征多项式
      • 特征矩阵&求解特征多项式
      • 常系数齐次线性递推优化
      • 暴力多项式取模
      • 模板


常系数齐次线性递推式

f k = ∑ i = 1 n a i f k − i f_k=\sum _{i=1}^{n} a_if_{k-i} fk=i=1naifki

形如上式的 d p dp dp转移式( f f f表示 d p dp dp状态, a a a表示转移系数)即为常系数齐次线性递推式。对于这样的 d p dp dp式,给定 f 1 , 2 , . . , n , a 1 , 2 , . . . , n f_{1,2,..,n},a_{1,2,...,n} f1,2,..,n,a1,2,...,n,即可递推出 f k ( k > n ) f_k(k>n) fk(k>n)

常系数:每一项均由前 n n n项乘以固定系数得到。齐次:都为一次式。线性递推:显然。

矩阵快速幂优化上式达到 O ( n 3 log ⁡ k ) O(n^3\log k) O(n3logk)的复杂度(但这不是本文的重点)。

而常系数齐次线性递推式的转移矩阵的特征多项式可以 O ( 读 入 ) O(读入) O()求出,所以通过特征多项式可以进一步优化到 O ( n 2 log ⁡ k ) O(n^2 \log k) O(n2logk),再进一步优化多项式取模后可以做到 O ( n log ⁡ n log ⁡ k ) O(n\log n\log k ) O(nlognlogk)(本文讲解 O ( n 2 log ⁡ k ) O(n^2\log k) O(n2logk)的暴力取模方法)。


特征值&特征向量&特征多项式

A A A n n n阶矩阵,如果存在常数 λ \lambda λ非零向量 v ⃗ \vec v v ,使得 A v ⃗ = λ v ⃗ A\vec v=\lambda\vec v Av =λv ,则称 λ \lambda λ A A A特征值(也称缩放系数),非零向量 v ⃗ \vec v v 为** A A A的对应于特征值 λ \lambda λ的特征向量**。

则:
A v ⃗ = λ v ⃗ ⟺ ( λ I − A ) v ⃗ = 0 A\vec v=\lambda \vec v \Longleftrightarrow (\lambda I-A)\vec v=0 Av =λv (λIA)v =0

其有非零解的充要条件: d e t ( λ I − A ) = ∣ λ I − A ∣ = 0 det(\lambda I -A)=|\lambda I-A|=0 det(λIA)=λIA=0
( d e t ( A ) , ∣ A ∣ det(A),|A| det(A),A是矩阵 A A A的行列式的两种等价的表示方式)
(并不会证明,似乎 d e t ( ) = 0 det()=0 det()=0的一个矩阵可以想象成拍扁成了向量?而一个可逆的( d e t ( ) ≠ 0 det()\neq 0 det()̸=0的矩阵乘上一个向量并不能得到0)。

方程 ∣ λ I − A ∣ = 0 |\lambda I-A|=0 λIA=0称为 A A A特征方程

A = a ( i j ) A=a(ij) A=a(ij)的秩(列秩/行秩)为 n n n(令 A A A是满秩的),则 A A A的有 n n n组线性不相关特征值和特征向量(唔,证明没有找到)。
则有:
( 1 ) λ 1 + λ 2 + . . . + λ n = a 11 + a 22 + . . . + a n n (1)\lambda_1 +\lambda_2+...+\lambda_n=a_{11}+a_{22}+...+a_{nn} (1)λ1+λ2+...+λn=a11+a22+...+ann
( 2 ) λ 1 λ 2 . . . λ n = ∣ A ∣ (2)\lambda_1\lambda_2...\lambda_n=|A| (2)λ1λ2...λn=A
结合 ∣ λ I − A ∣ = 0 |\lambda I-A|=0 λIA=0可以简单证明(理解)。

∣ λ I − A ∣ = λ n + k 1 λ n − 1 + . . . + k n − 1 λ + k n |\lambda I-A|=\lambda^n+k_1\lambda^{n-1}+...+k_{n-1}\lambda +k^n λIA=λn+k1λn1+...+kn1λ+kn这个 λ \lambda λ n n n次多项式称为 A A A特征多项式 ϕ ( λ ) \phi(\lambda) ϕ(λ)
也即 ϕ ( x ) = ∣ x I − A ∣ \phi(x)=|xI-A| ϕ(x)=xIA
ϕ ( λ ) = 0 \phi(\lambda)=0 ϕ(λ)=0 n n n个解即为 A A A n n n个特征值。


特征矩阵&求解特征多项式

λ I − A = [ λ − a 11 − a 12 ⋯ − a 1 n − a 21 λ − a 22 ⋯ − a 2 n ⋯ ⋯ ⋯ ⋯ − a n 1 − a n 2 ⋯ λ − a n n ] \lambda I-A=\left [ \begin {matrix} \lambda -a_{11} & -a_{12} & \cdots & -a_{1n} \\ -a_{21} & \lambda -a_{22} &\cdots & -a_{2n} \\ \cdots & \cdots & \cdots & \cdots &\\ -a_{n1} & -a_{n2} &\cdots & \lambda -a_{nn}\\ \end {matrix} \right ] λIA=λa11a21an1a12λa22an2a1na2nλann
该矩阵称为 A A A特征矩阵

回归到常系数齐次线性递推式 f k = ∑ i = 1 n a i f k − i f_k=\sum _{i=1}^{n} a_if_{k-i} fk=i=1naifki
[ a 1 a 2 a 3 ⋯ a n − 1 a n 1 0 0 ⋯ 0 0 0 1 0 ⋯ 0 0 0 0 1 ⋯ 0 0 ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ 0 0 0 ⋯ 0 0 0 0 0 ⋯ 1 0 ] [ f k − 1 f k − 2 f k − 3 f k − 4 ⋮ f k − ( n − 1 ) f k − n ] = [ f k f k − 1 f k − 2 f k − 3 ⋮ f k − ( n − 2 ) f k − ( n − 1 ) ] \left [ \begin {matrix} a_1 &a_2 & a_3& \cdots &a_{n-1} &a_n\\ 1 & 0&0& \cdots & 0 & 0\\ 0& 1 & 0 &\cdots &0&0\\ 0 & 0&1& \cdots &0&0\\ \cdots &\cdots &\cdots &\cdots &\cdots &\cdots &\\ 0&0&0&\cdots &0 &0\\ 0&0&0&\cdots &1&0 \\ \end {matrix} \right] \left [ \begin{matrix} f_{k-1}\\f_{k-2}\\ f_{k-3}\\f_{k-4}\\ \vdots\\f_{k-(n-1)} \\f_{k-n} \end{matrix} \right ] = \left [ \begin{matrix} f_{k}\\f_{k-1}\\ f_{k-2}\\f_{k-3}\\ \vdots\\f_{k-(n-2)} \\f_{k-(n-1)} \end{matrix} \right ] a110000a201000a300100an100001an00000fk1fk2fk3fk4fk(n1)fkn=fkfk1fk2fk3fk(n2)fk(n1)
构造转移矩阵的特征矩阵:
ϕ ( λ ) = ∣ λ I − A ∣ = [ λ − a 1 − a 2 − a 3 ⋯ − a n − 1 − a n − 1 λ 0 ⋯ 0 0 0 − 1 λ ⋯ 0 0 0 0 − 1 ⋯ 0 0 ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ 0 0 0 ⋯ λ 0 0 0 0 ⋯ − 1 λ ] \phi(\lambda)=|\lambda I-A|= \left [ \begin {matrix} \lambda -a_1 & -a_2 & -a_3& \cdots &-a_{n-1} &-a_n\\ -1 & \lambda&0& \cdots & 0 & 0\\ 0& -1 & \lambda &\cdots &0&0\\ 0 & 0&-1& \cdots &0&0\\ \cdots &\cdots &\cdots &\cdots &\cdots &\cdots &\\ 0&0&0&\cdots &\lambda &0\\ 0&0&0&\cdots &-1&\lambda \\ \end {matrix} \right] ϕ(λ)=λIA=λa110000a2λ1000a30λ100an1000λ1an0000λ
这里可以强行手算一下行列式(全排列逆序对方法),因为这个矩阵每列最多只有三行不为0,所以可以模拟/枚举一下:

  • 选中第一列第一排的 λ − a 1 \lambda -a_1 λa1,由于每排每列只能选一个,且不能选0,则只有一种方案:沿对角线选择。贡献为: λ n − 1 ( λ − a 1 ) \lambda^{n-1}(\lambda -a_1) λn1(λa1)
  • 选中第一列第二排的 − 1 -1 1,可以想到在有一列选中第一排之前,每一列 i i i都只能选第 i + 1 i+1 i+1排的数1(第 i i i排被上一列占了),选了第一排后,为保证有解,剩下的列都只能选对角线上的数,所以结合逆序对,总贡献为: ∑ i = 2 n ( − a i ) ( − 1 ) i − 1 λ n − i ( − 1 ) i − 1 = − ∑ i = 2 n a i λ n − i \sum_{i=2}^n(-a_i)(-1)^{i-1}\lambda^{n-i}(-1)^{i-1}=-\sum_{i=2}^n a_i\lambda ^{n-i} i=2n(ai)(1)i1λni(1)i1=i=2naiλni

综上:
(1) ϕ ( λ ) = ∣ λ I − A ∣ = λ n − ∑ i = 1 n a i λ n − i \phi(\lambda)=|\lambda I-A|=\lambda ^{n}-\sum_{i=1}^n a_i\lambda ^{n-i}\tag 1 ϕ(λ)=λIA=λni=1naiλni(1)
这样就得到了特征多项式的每项系数。


常系数齐次线性递推优化

ϕ ( A ) = ∣ A I − A ∣ = 0 \phi(A)=|AI-A|=0 ϕ(A)=AIA=0得到 ϕ ( A ) \phi(A) ϕ(A)为0矩阵。

但似乎上面这个证明是错的?

前文已经说明 ϕ ( x ) \phi(x) ϕ(x)是一个 n n n次多项式,同样由 ϕ ( λ ) = 0 \phi(\lambda)=0 ϕ(λ)=0可以用插值法表达为: ϕ ( x ) = ∏ i = 1 n ( λ i − x ) \phi(x)=\prod \limits_{i=1}^n (\lambda_i -x) ϕ(x)=i=1n(λix)

ϕ ( A ) = ∏ i = 1 n ( λ i I − A ) \phi(A)=\prod \limits_{i=1}^n (\lambda_iI-A) ϕ(A)=i=1n(λiIA)。显然对于所有 1 ≤ i ≤ n 1\leq i\leq n 1in都有 ϕ ( A ) v ⃗ i = 0 \phi(A)\vec v_i=0 ϕ(A)v i=0,又因为 v ⃗ i \vec v_i v i互相线性不相关,所以 A A A变换得到的 ϕ ( A ) \phi(A) ϕ(A)矩阵为0矩阵。得证。

假设原本需要矩阵快速幂求得 A k A^{k} Ak,现在去掉无用的 0 0 0矩阵,答案是相同的,实际上就是多项式取模的过程,最终得到一个最高次幂为 n − 1 n-1 n1次的多项式 g ( A ) g(A) g(A)
(2) g ( A ) = A k % ϕ ( A ) = ∑ i = 0 n − 1 p i A i g(A)=A^k\%\phi(A)=\sum _{i=0}^{n-1} p_i A^i\tag 2 g(A)=Ak%ϕ(A)=i=0n1piAi(2)

设初始递推矩阵为: f [ 1 ] = f n , f n − 1 , . . . , f 1 f[1]=f_n,f_{n-1},...,f_1 f[1]=fn,fn1,...,f1,则最终得到: f [ 1 ] A k = f [ 1 ] g ( A ) = f [ 1 + k ] f[1]A^k=f[1]g(A)=f[1+k] f[1]Ak=f[1]g(A)=f[1+k],进一步转化为 f [ 1 + k ] = ∑ i = 0 n − 1 p i f [ 1 + i ] f[1+k]=\sum\limits_{i=0}^{n-1}p_if[1+i] f[1+k]=i=0n1pif[1+i],但实际上我们只需要 f [ 1 + k ] f[1+k] f[1+k]中的最后一项 f 1 + k f_{1+k} f1+k,可以将矩阵加法展开,故:
(3) f 1 + k = ∑ i = 0 n − 1 p i f 1 + i f_{1+k}=\sum\limits_{i=0}^{n-1}p_if_{1+i}\tag 3 f1+k=i=0n1pif1+i(3)

常系数齐次线性递推优化的过程即为:

( 1 ) (1) (1)求出转移矩阵 A A A的特征多项式 ϕ ( A ) \phi(A) ϕ(A)

( 2 ) (2) (2) ϕ ( A ) \phi(A) ϕ(A)为模做 A A A的快速幂得到 A k A^k Ak

( 3 ) (3) (3)解出 n − 1 n-1 n1次多项式 g ( A ) g(A) g(A)的每项系数转移得到答案


暴力多项式取模

这里补充一点知识:

关于多项式取模法则:
如: 5 x 5 + 3 x 4 + x 3 + x 2 + 6 x + 1 m o d    ( x 3 + x 2 + x + 1 ) 5x^5+3x^4+x^3+x^2+6x+1 \mod (x^3+x^2+x+1) 5x5+3x4+x3+x2+6x+1mod(x3+x2+x+1)
我们先把 ( x 3 + x 2 + x + 1 ) (x^3+x^2+x+1) (x3+x2+x+1)乘以 x 2 x^2 x2,把被除的多项式中的 5 x 5 5x^5 5x5 消掉(做减法)
然后以此把次高位消掉,直到消到 x 3 x^3 x3为止。
来源

这是一个 O ( n 2 ) O(n^2) O(n2)的暴力取模。

O ( n log ⁡ n ) O(n\log n) O(nlogn)的取模看这里。


模板

bzoj4161

一道真·模板

#include
#define gc getchar()
#define si isdigit(ch)
#define RI register
using namespace std;

const int N=4002,mod=1e9+7;
int ans,n,K,a[N],b[N],c[N],e[N],re[N];

char ch; 
inline void rd(int &x)
{
	ch=gc;x=0;int f=0;
	for(;!si;ch=gc) if(ch=='-') f=1;
	for(;si;ch=gc) x=x*10+(ch^48);
	if(f) x=mod-x;
} 

inline int ad(int x,int y){x+=y;return x>=mod? x-mod:x;}
inline int dc(int x,int y){x-=y;return x<0? x+mod:x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}

inline void Mul(int *f,int *g,int n)
{
	RI int i,j;
	memset(re,0,sizeof(int)*(n+1));
	for(i=0;i<=K;++i)
	 for(j=0;j<=K;++j)
	  re[i+j]=ad(re[i+j],mul(f[i],g[j]));
	for(i=n;i>=K;--i){
		if(!re[i]) continue;
		for(j=0;j>=1,Mul(c,c,M))
	 if(n&1) Mul(c,e,M);
	for(i=0;i

bzoj4944 noi2017泳池

#include
#define RI register
using namespace std;
const int mod=998244353;
const int N=2005;
int a[N],e[N],c[N],b[N],f[2][N],ss[N];
int pw[N],rvq,q,n,lim,xx,yy,ans;

inline int ad(int x,int y){x+=y;return x>=mod? x-mod:x;}
inline int dc(int x,int y){x-=y;return x<0? x+mod:x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}

inline int fp(int x,int y)
{
	int re=1;
	for(;y;y>>=1,x=mul(x,x))
	 if(y&1) re=mul(re,x);
	return re;
}

inline void Mul(int *f,int *g,int n,int K)
{
	RI int i,j,k,t;
	memset(ss,0,sizeof(int)*(n+1));
	for(i=0;i=K;--i){
		if(!ss[i]) continue;
		for(j=1;j<=K;++j)
		 ss[i-j]=ad(ss[i-j],mul(ss[i],b[j]));
		ss[i]=0;
	}
	for(i=0;i<=K;++i) g[i]=ss[i];
}

inline int cal(int n,int lim)
{
	RI int i,j,k,t,ori;
	memset(f[1],0,sizeof(f[1]));
	int *F=f[0],*G=f[1];G[0]=1;
	for(i=lim-1;i;--i,swap(F,G)){
		memset(F,0,sizeof(int)*(lim+1));
		for(j=0;i*j>=1,Mul(c,c,t,ori))
     if(n&1) Mul(c,e,t,ori);
	for(ans=0,i=0;i

你可能感兴趣的:(---线性代数---,矩阵行列式,矩阵加速DP,特征多项式)