zoukankan      html  css  js  c++  java
  • CH定理与线性递推

    才发觉自己数学差的要死,而且脑子有点浑浑噩噩的,学了一个晚上才学会

    如果说的有什么不对的可以在下面嘲讽曲明

    以下无特殊说明时,默认方阵定义在实数域上,用(|A|)表示(A)的行列式

    特征值与特征向量

    对于一个(n)阶方阵(A),如果存在某个列向量(v)(lambdain R),使得

    [egin{aligned} Av=lambda v end{aligned} ]

    则我们称(v)为矩阵(A)的特征向量,(lambda)为对应的特征值

    不难发现上面的等式可以写成

    [egin{aligned} (lambda E-A)v=0 end{aligned} ]

    根据线代的基本芝士,可以得知

    一,如果(A)满秩,则(A)(n)组线性无关的特征向量

    二,如果(|lambda E-A|=0),则存在(v)使等式成立,否则不存在

    Cayley-Hamilton定理

    假设(A)满秩。记(A)的特征多项式为(f(lambda)=|lambda E-A|),其中(lambda)代表未知数。通过暴力展开行列式易知(f)是关于(lambda)的一个(n)次多项式,设其为(f(lambda)=lambda^n+sum_{i=1}^na_ilambda^{n-i}),则(f(A)=A^n+sum_{i=1}^na_iA^{n-i}=0)

    可以跳过证明直接看下面了

    对于(f(lambda)),它的(n)个根为(lambda_k),其中(lambda_{k})表示(A)的第(k)个特征值,所以不考虑常数倍时,它可以写成

    [egin{aligned} f(lambda)=prod_{k}(lambda_{k}-lambda) end{aligned} ]

    所以我们需要证明下列等式恒成立

    [egin{aligned} prod_{k}(lambda_{k} E-A)=0 end{aligned} ]

    直接证明它为(0)很难,我们可以考虑证明任意向量乘上它为(0)

    因为它的(n)组特征向量线性无关,所以任意向量都可以被这(n)组特征向量表示,那么只要证明任意特征向量乘上它为(0)即可

    首先,可以证明它满足交换律

    [egin{aligned} (aE-A)(bE-A)=abE^2-aEA-bEA+A^2=(bE-A)(aE-A) end{aligned} ]

    那么就可以把里面的给提出来

    [egin{aligned} v_iprod_{k}(lambda_{k} E-A)=v_i(lambda_{i} E-A)prod_{k eq i}(lambda_{k} E-A)=0 end{aligned} ]

    就没了

    线性递推

    先考虑求出(f(lambda)),对于(|lambda E-A|),我们写出这个矩阵,并对第一列展开,可得(f(lambda)=lambda^n-sum_{i=1}^na_ilambda^{n-i}),于是我们可以得到(f(A))的系数了

    递推关系为

    [egin{aligned} h_i=sum_{j=1}^na_jh_{i-j} end{aligned} ]

    (h_{0,...,n-1})已给出,求(h_k)

    我们记初始向量为(S),其中(S_i=h_i),转移矩阵为(A),以及(B(x)=f(A)),那么最终要求的就是((S imes A^n)_0)

    我们记(C(A)equiv A^npmod{B(A)}),由于(B=0),所以(C(A)=A^{n})

    注意这里模一个零多项式不会有问题,因为取模相等于减去若干个(B(A))

    而且由于(C(A))是模(B(A))后的多项式,所以(C(A))的次数小于(n),即(C(A))可以写成(sum_{i=0}^{n-1}c_iA^i)

    那么最终要求的柿子就可以写成

    [egin{aligned} (S imes A^n)_0 &=(S imes sum_{i=0}^{n-1}c_iA^i)_0\ &=sum_{i=0}^{n-1}c_i(S imes A^i)_0\ end{aligned} ]

    这里(S imes A^i),事实上就是(S_i),所以最终的答案就是

    [egin{aligned} h_n=sum_{i=0}^{n-1}c_ih_i end{aligned} ]

    (C)的话,用多项式快速幂+取模即可,如果都是暴力实现的话复杂度是(O(n^2log k)),如果用(NTT)可以优化到(O(nlog n log k))

    bzoj4161,暴力

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    const int P=1e9+7;
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    inline int inc(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
        R int res=1;
        for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
        return res;
    }
    const int N=2005;
    typedef vector<int> poly;
    int a[N],b[N],L,n,res;poly c,d,md;
    poly operator %(R poly a,R poly b){
        R int n=a.size(),m=b.size(),t,iv=inc(0,P-ksm(b[m-1],P-2));
        fd(i,n-1,m-1)if(a[i]){
            t=mul(a[i],iv);
            fp(j,0,m-1)upd(a[i-j],mul(t,b[m-1-j]));
        }
        while(!a.empty()&&!a.back())a.pop_back();
        return a;
    }
    poly operator *(R poly a,R poly b){
        R int n=a.size(),m=b.size();poly c(n+m-1);
        fp(i,0,n-1)fp(j,0,m-1)upd(c[i+j],mul(a[i],b[j]));
        return c%md;
    }
    int main(){
    //  freopen("testdata.in","r",stdin);
        scanf("%d%d",&L,&n);
        fp(i,1,n)scanf("%d",&a[i]),upd(a[i],P);
        fp(i,0,n-1)scanf("%d",&b[i]),upd(b[i],P);
        md.resize(n+1);md[n]=1;fp(i,0,n-1)md[i]=inc(0,P-a[n-i]);
        c.resize(1),d.resize(2),c[0]=1,d[1]=1;
        for(;L;L>>=1,d=d*d)if(L&1)c=c*d;
        res=0;
        fp(i,0,n-1)upd(res,mul(c[i],b[i]));
        printf("%d
    ",res);
        return 0;
    }
    

    洛谷4723 NTT优化

    常数极大,极大

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    const int P=998244353;
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    inline int inc(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    	return res;
    }
    const int N=(1<<17)+5;
    int rt[2][N],r[18][N],inv[18],lg[N],md[N],A[N],B[N],a[N],b[N],lim,d,n,K;
    void init(){
    	fp(d,1,16){
    		fp(i,1,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));
    		inv[d]=ksm(1<<d,P-2),lg[1<<d]=d;
    	}
    	for(R int t=(P-1)>>1,i=1,x,y;i<65536;t>>=1,i<<=1){
    		x=ksm(3,t),y=ksm(332748118,t),rt[0][i]=rt[1][i]=1;
    		fp(k,1,i-1){
    			rt[0][i+k]=mul(rt[0][i+k-1],x);
    			rt[1][i+k]=mul(rt[1][i+k-1],y);
    		}
    	}
    }
    void NTT(int *A,int ty){
    	int t;
    	fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]);
    	for(R int mid=1;mid<lim;mid<<=1)
    		for(R int j=0;j<lim;j+=(mid<<1))
    			fp(k,0,mid-1){
    				A[j+k+mid]=inc(A[j+k],P-(t=mul(A[j+k+mid],rt[ty][mid+k])));
    				upd(A[j+k],t);
    			}
    	if(!ty){
    		t=inv[d];
    		fp(i,0,lim-1)A[i]=mul(A[i],t);
    	}
    }
    void Inv(int *a,int *b,int len){
    	if(len==1)return b[0]=ksm(a[0],P-2),void();
    	Inv(a,b,len>>1);
    	static int A[N],B[N];lim=(len<<1),d=lg[lim];
    	fp(i,0,len-1)A[i]=a[i],B[i]=b[i];
    	fp(i,len,lim-1)A[i]=B[i]=0;
    	NTT(A,1),NTT(B,1);
    	fp(i,0,lim-1)A[i]=mul(A[i],mul(B[i],B[i]));
    	NTT(A,0);
    	fp(i,0,len-1)upd(b[i],inc(b[i],P-A[i]));
    	fp(i,len,lim-1)b[i]=0;
    }
    void Mod(int *a,int *b,int *c,int n,int m){
    	while(!a[n-1])--n;
    	if(n<m){
    		fp(i,0,n-1)c[i]=a[i];fp(i,n,m-2)c[i]=0;
    		return;
    	}
    	static int A[N],B[N],IB[N],C[N];
    	R int len=1;while(len<=n-m)len<<=1;
    	fp(i,0,n-1)A[i]=a[n-i-1];fp(i,0,m-1)B[i]=b[m-i-1];
    	fp(i,m,len-1)B[i]=0;Inv(B,IB,len);
    	lim=(len<<1),d=lg[lim]; 
    	fp(i,n-m+1,lim-1)A[i]=IB[i]=0;
    	NTT(A,1),NTT(IB,1);
    	fp(i,0,lim-1)A[i]=mul(A[i],IB[i]);
    	NTT(A,0);
    	lim=1;while(lim<n)lim<<=1;d=lg[lim];
    	fp(i,0,n-m)C[i]=A[n-m-i];fp(i,n-m+1,lim-1)C[i]=0;
    	fp(i,0,m-1)B[i]=b[i];fp(i,m,lim-1)B[i]=0;
    	NTT(B,1),NTT(C,1);
    	fp(i,0,lim-1)B[i]=mul(B[i],C[i]);
    	NTT(B,0);
    	fp(i,0,m-2)c[i]=inc(a[i],P-B[i]);
    	fp(i,m-1,lim-1)c[i]=0;
    }
    void Mul(int *a,int *b,int *c,int n,int m){
    	static int A[N],B[N];
    	lim=1;while(lim<(n+m))lim<<=1;d=lg[lim];
    	fp(i,0,n-1)A[i]=a[i];fp(i,0,m-1)B[i]=b[i];
    	fp(i,n,lim-1)A[i]=0;fp(i,m,lim-1)B[i]=0;
    	NTT(A,1),NTT(B,1);
    	fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
    	NTT(A,0);
    	fp(i,n+m-1,lim-1)A[i]=0;
    	Mod(A,md,c,n+m-1,K+1);
    }
    void ksm(int y){
    	R int sz=2,psz=1;
    	A[1]=1,B[0]=1;
    	for(;y;y>>=1,Mul(A,A,A,sz,sz),sz=sz+sz-1,cmin(sz,K))
    		if(y&1)Mul(A,B,B,sz,psz),psz+=sz-1,cmin(psz,K);
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	init();
    	scanf("%d%d",&n,&K);
    	fp(i,1,K)scanf("%d",&a[i]),upd(a[i],P);
    	fp(i,0,K-1)scanf("%d",&b[i]),upd(b[i],P);
    	md[K]=1;fp(i,0,K-1)md[i]=inc(0,P-a[K-i]);
    	ksm(n);
    	R int res=0;
    	fp(i,0,K-1)upd(res,mul(B[i],b[i]));
    	printf("%d
    ",res);
    	return 0;
    }
    

    参考文献

    https://www.luogu.org/blog/ShadowassIIXVIIIIV/solution-p4723

    https://blog.csdn.net/qq_39972971/article/details/80732541

  • 相关阅读:
    Python之美[从菜鸟到高手]--Python垃圾回收机制及gc模块详解
    linux-memory-buffer-vs-cache
    MYSQL----myownstars(102)
    win10系统调用架构分析
    on io scheduling again
    Java并发编程
    elixir-lang
    mydumper工作原理, seconds_behind_master的陷阱和pt-heartbeat (102)
    深入理解JavaScript系列+ 深入理解javascript之执行上下文
    我们应该如何去了解JavaScript引擎的工作原理 系列
  • 原文地址:https://www.cnblogs.com/yuanquming/p/11908670.html
Copyright © 2011-2022 走看看