zoukankan      html  css  js  c++  java
  • 矩阵快速幂

    板子

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 110
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    const int mod=1e9+7;
    ll n,k;
    
    struct Matrix{
    	int m,n;
    	ll a[maxn][maxn];
    	
    	inline void init(int _m=0,int _n=0){
    		m=_m;n=_n;
    		memset(a,0,sizeof a);
    	}
        
        inline Matrix operator + (Matrix B){
    		Matrix res;
            res.init(m,n);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    res.a[i][j]=a[i][j]+B.a[i][j];
            return res;
        }
        
        inline Matrix operator - (Matrix B){
    		Matrix res;
            res.init(m,n);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    res.a[i][j]=(a[i][j]-B.a[i][j]+mod)%mod;
            return res;
        }
        
        inline Matrix operator * (int c){
    		Matrix res;
            res.init(m,n);
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
                    res.a[i][j]=c*a[i][j];
            return res;
        }
    	
    	inline Matrix operator * (Matrix B){
    		Matrix res;
    		res.init(m,B.n);
    		for(int i=1;i<=m;i++)
    			for(int j=1;j<=B.n;j++)
    				for(int k=1;k<=n;k++)
    					(res.a[i][j]+=a[i][k]*B.a[k][j])%=mod;
    		return res;
    	}
    	
    	inline void id(){
    		for(int i=1;i<=n;i++) a[i][i]=1;
    	}
    	
    	inline Matrix qpow(ll t){
    		Matrix res;
    		res.init(m,m);
    		res.id();
    		Matrix tmp=*this;
    		for(;t;t>>=1,tmp=tmp*tmp) if(t&1) res=res*tmp;
    		return res;
    	}
    
    };
    
    int main(){
    	read(n),read(k);
    	Matrix s,ans;
    	s.init(n,n);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			read(s.a[i][j]);
    	ans=s.qpow(k);
    	for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                printf("%lld ",ans.a[i][j]);
            }
            cout<<endl;
        }
    	return 0;
    }
    

    例题

    Lougu P1939矩阵加速

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define int long long//不开long long的话会爆int 
    using namespace std;
    
    const int mod=1e9+7;
    int t,n;
    
    struct matrix{
        int a[4][4];
        matrix(){
            memset(a,0,sizeof(a));
        }
        inline void build(){
            for(int i=1;i<=3;i++) a[i][i]=1;
        }
        matrix friend operator * (matrix x,matrix y){
            matrix res;
            for(int i=1;i<=3;i++)
                for(int j=1;j<=3;j++)
                    for(int k=1;k<=3;k++)
                        (res.a[i][j]+=x.a[i][k]*y.a[k][j]%mod)%=mod;
            return res;
        }
    };
    
    inline matrix qpow(matrix a,int t){
        matrix res;
        res.build(); 
        for(;t;t>>=1,a=a*a)
            if(t&1) res=res*a;
        return res;
    }
    
    signed main(){
        cin>>t;
        for(int i=1;i<=t;i++){
            cin>>n;
            if(n<=3){
                cout<<1<<endl;
                continue;
            }
            matrix s;
            memset(s.a,0,sizeof(s.a));
            s.a[1][1]=s.a[1][2]=s.a[2][3]=s.a[3][1]=1;
            s=qpow(s,n-2);
            cout<<(s.a[1][1]+s.a[1][3])%mod<<endl;
        }
        return 0;
    }
    

    Luogu P1962斐波那契数列

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<string.h>
    #define ll long long
    using namespace std;
    const int mod=1e9+7;
    
    ll n;
    
    struct Matrix{
        ll m,n;
        ll a[3][3];
        Matrix(){
            memset(a,0,sizeof(a));
        }
        inline void build(){
            for(int i=1;i<=2;i++) a[i][i]=1;
        }
        Matrix friend operator * (Matrix x,Matrix y){
            Matrix res;
            for(int i=1;i<=2;i++)
                for(int j=1;j<=2;j++)
                    for(int k=1;k<=2;k++)
                        (res.a[i][j]+=x.a[i][k]*y.a[k][j]%mod)%=mod;
            return res;
        }
        
    };
    
    inline Matrix qpow(Matrix a,ll t){
        Matrix res;
        res.build();
        for(;t;t>>=1,a=a*a)
            if(t&1) res=res*a;
        return res;
    }
    
    int main(){
        cin>>n;
        if(n==1){cout<<1<<endl;return 0;}
        if(n==2){cout<<1<<endl;return 0;}
        Matrix s;
        s.a[1][1]=s.a[1][2]=s.a[2][1]=1;
        s=qpow(s,n-2);
        cout<<(s.a[1][1]+s.a[1][2])%mod<<endl;
        return 0;
    }
    

    Luogu P1707刷题比赛

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define N 20
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    ll n,mod,p,q,r,t,u,v,w,x,y,z;
    
    ll qmul(ll a, ll b) {
    	ll res = 0;
    	for(; b; b >>= 1, a = (a << 1) % mod) if(b & 1) res = (res + a) % mod;
    	return res;
    }
    
    struct Matrix {
    	int m, n;
    	ll a[N][N];
    	void init(int _m, int _n) {
    		m = _m, n = _n;
    		memset(a, 0, sizeof(a));
    	}
    	Matrix operator * (Matrix B) {
    		Matrix res;
    		res.init(m, B.n);
    		for(int i = 1; i <= m; i ++)
    			for(int j = 1; j <= B.n; j ++)
    				for(int k = 1; k <= n; k ++)
    					res.a[i][j] = (res.a[i][j] + qmul(a[i][k], B.a[k][j])) % mod;
    		return res;
    	}
    	void id() {
    		for(int i = 1; i <= m; i ++)
    			a[i][i] = 1;
    	}
    	Matrix fpow(ll k) {
    		Matrix res, tmp = *this;
    		res.init(m, n);
    		res.id();
    		for(; k; k >>= 1, tmp = tmp * tmp) if(k & 1) res = res * tmp;
    		return res;
    	}
    };
    
    int main() {
    	read(n),read(mod);
    	read(p),read(q),read(r),read(t);
        read(u),read(v),read(w);
        read(x),read(y),read(z);
    	if(n<=2){
    		printf("nodgd %d
    ",n==2?3:1);
    		printf("Ciocio %d
    ",n==2?3:1);
    		printf("Nicole %d",n==2?3:1);
    		return 0;
    	} 
    	else n-=2;
    	ll s[N*N]={
    		p, q, 1, 0, 1, 0, r, 2*r+t, r+t+1, 0, 0,
    		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    		1, 0, u, v, 1, 0, 0, 0, 0, w, 0,
    		0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
    		1, 0, 1, 0, x, y, 0, 1, 3, 0, z,
    		0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
    		0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0,
    		0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
    		0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
    		0, 0, 0, 0, 0, 0, 0, 0, 0, w, 0,
    		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z,
    		3, 1, 3, 1, 3, 1, 0, 0, 1, 1, 1
    	};
    	Matrix op,ans;
    	op.init(11,11);ans.init(11,1);
    	int cnt=0;
    	for(int i=1;i<=11;i++)
    		for(int j=1;j<=11;j++)
    			op.a[i][j]=s[cnt++];
    	for(int i=1;i<=11;i++) ans.a[i][1]=s[cnt++];
    	op=op.fpow(n);
    	op=op*ans;
    	cout<<"nodgd "<<op.a[1][1]<<endl;
        cout<<"Ciocio "<<op.a[3][1]<<endl;
        cout<<"Nicole "<<op.a[5][1]<<endl;
    	return 0;
    }
    

    Luogu P1397矩阵游戏

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 1000010
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0;bool flag=0;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    const int mod=1e9+7;
    ll a,b,c,d;
    char n[maxn],m[maxn];
    
    ll md(ll x){
    	return x>mod?x-mod:x;
    }
    
    struct Matrix{
        ll s[3][3];
        Matrix(){
            memset(s,0,sizeof(s));
        }
        inline void build(){
            for(int i=1;i<=2;i++) s[i][i]=1;
        }
    }m1,m2;
    
    Matrix operator * (Matrix x,Matrix y){
        Matrix res;
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++)
                	res.s[i][j]=md(res.s[i][j]+(x.s[i][k]*y.s[k][j])%mod);
        return res;
    }
    
    inline Matrix qpow_(Matrix a,ll b){
    	Matrix res;
    	res.build();
    	for(;b;b>>=1,a=a*a) if(b&1) res=res*a;
    	return res;
    }
    
    inline Matrix qpow(Matrix a,char *b){
    	int x=strlen(b)-1;
        Matrix res;
        res.build();
        for(int i=x;i>=0;i--){
        	res=res*qpow_(a,b[i]-'0');
        	a=qpow_(a,10);
        }
        return res;
    }
    
    void pre(){
        m1.s[1][1]=a,m1.s[1][2]=b,m1.s[2][1]=0,m1.s[2][2]=1;
        m2.s[1][1]=c,m2.s[1][2]=d,m2.s[2][1]=0,m2.s[2][2]=1;
    }
    
    int main(){
        scanf("%s",&n);scanf("%s",&m);
        ll lenn=strlen(n)-1,lenm=strlen(m)-1;
        for(int i=lenn;i>=0;i--){
            if(n[i]=='0') n[i]='9';
            else {n[i]=n[i]-1; break;}
        }
        for(int i=lenm;i>=0;i--){
            if(m[i]=='0') m[i]='9';
            else {m[i]=m[i]-1; break;}
        }
        read(a),read(b),read(c),read(d);
        pre();
        m1=qpow(m1,m);
        m2=m2*m1;
        m2=m1*qpow(m2,n);
        ll ans=md(m2.s[1][1]+m2.s[1][2]);
        cout<<ans<<endl;
        return 0;
    }//gaojing
    

    Luogu P3758可乐

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 110
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    const int mod=2017;
    int n,m,u,v,t;
    int ans;
    
    struct Matrix {
    	int m, n;
    	int a[maxn][maxn];
    
    	void init(int _m, int _n) {
    		m = _m, n = _n;
    		memset(a, 0, sizeof(a));
    	}
    
    	Matrix operator * (Matrix B) {
    		Matrix res;
    		res.init(m, B.n);
    		for(int i = 1; i <= m; i ++)
    			for(int j = 1; j <= B.n; j ++)
    				for(int k = 1; k <= n; k ++)
    					res.a[i][j] = (res.a[i][j] + (a[i][k] * B.a[k][j])%mod) % mod;
    		return res;
    	}
    
    	void build() {
    		for(int i = 1; i <= m; i ++) a[i][i] = 1;
    	}
    
    //	Matrix qpow(int k) {
    //		Matrix res, tmp = *this;
    //		res.init(m, m);
    //		res.build();
    //		for(; k; k >>= 1, tmp = tmp * tmp) if(k & 1) res = res * tmp;
    //		return res;
    //	}
    };
    
    inline Matrix qpow(Matrix &a,int b){
    	Matrix res;
    	res.init(n,n);
    	res.build();
    	for(;b;b>>=1,a=a*a) if(b&1) res=res*a;
    	return res;
    }
    
    int main(){
    	Matrix s;
        read(n),read(m);
        s.init(n+1,n+1);
        for(int i=1;i<=m;i++){
            read(u),read(v);
            s.a[u][v]=1;s.a[v][u]=1;
        }
        read(t);
        for(int i=1;i<=n+1;i++) s.a[i][i]=1;
        for(int i=1;i<=n+1;i++) s.a[i][n+1]=1;
        Matrix tot=qpow(s,t);
    //    (int i=1;i<=n;i++){
    //    	for(int j=1;j<=n;j++) cout<<s.a[i][j]<<" ";
    //    	cout<<endl;
    //    }
        for(int i=1;i<=n+1;i++) ans=(ans+tot.a[1][i])%mod;
        cout<<ans<<endl;
        return 0;
    }
    

    Luogu P4159迷路

    题目

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 110
    #define ll int
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    const int mod=2009;
    int n,t,nn;
    char c[15];
    
    int check(int a,int b){
    	return 9*(a-1)+b;
    }
    
    struct Matrix{
    	ll m,n;
    	ll a[maxn][maxn];
    	
    	inline void init(int _m=0,int _n=0){
    		m=_m,n=_n;
    		memset(a,0,sizeof(a));
    	}
    
    	inline void build(){
    		for(int i=1;i<=m;i++) a[i][i]=1;
    	}
    	
    	Matrix operator * (Matrix B){
    		Matrix res;
    		res.init(m,B.n);
    		for(int i=1;i<=m;i++)
    			for(int j=1;j<=B.m;j++)
    				for(int k=1;k<=n;k++)
    					res.a[i][j]=(res.a[i][j]+(a[i][k]*B.a[k][j])%mod)%mod;
    		return res;
    	}
    	
    };
    
    inline Matrix qpow(Matrix &a,ll b){
    	Matrix res;
    	res.init(n,n);
    	res.build();
    	for(;b;b>>=1,a=a*a) if(b&1) res=res*a;
    	return res;
    }
    
    int main(){
        cin>>n>>t;
        nn=9*n;
        Matrix s;
        s.init(nn,nn);
    //    cout<<1<<endl;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=8;j++){
                s.a[check(i,j)][check(i,j+1)]=1;
            }
    //        cout<<2<<endl;
            for(int j=1;j<=n;j++){
                cin>>c[j];
                if(c[j]!='0') s.a[check(i,c[j]-'0')][check(j,1)]=1;
            }
        }
        s=qpow(s,t);
        cout<<s.a[1][9*n-8]%mod<<endl;
        return 0;
    }
    

    Luogu P2579沼泽鳄鱼

    题目

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<vector>
    #define maxn 60
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0;bool flag=0;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    const int mod=10000;
    int n,m,st,en,k,nfish,x,y;
    int r,rr[maxn];
    
    struct Matrix{
    	int m,n;
    	int a[maxn][maxn];
    	
    	inline void init(int _m=0,int _n=0){
    		m=_m;n=_n;
    		memset(a,0,sizeof a);
    	}
    	
    	inline void build(){
    		for(int i=0;i<m;i++) a[i][i]=1;
    	}
    	
    	inline Matrix operator * (Matrix B){
    		Matrix res;
    		res.init(m,B.n);
    		for(int i=0;i<m;i++)
    			for(int j=0;j<B.m;j++)
    				for(int k=0;k<n;k++)
    					(res.a[i][j]+=a[i][k]*B.a[k][j]%mod)%=mod;
    		return res;
    	}
    	
    	inline Matrix fpow(int t){
    		Matrix res;
    		res.init(m,m);
    		res.build();
    		Matrix tmp=*this;
    		for(;t;t>>=1,tmp=tmp*tmp) if(t&1) res=res*tmp;
    		return res;
    	}
    };
    
    Matrix B,T[13],S;
    vector<int> s;
    
    int main(){
    	read(n),read(m),read(st),read(en),read(k);
    	B.init(n,n);
    	for(int i=1;i<=m;i++){
    		read(x),read(y);
    		B.a[x][y]=1;
    		B.a[y][x]=1;
    	}
    	for(int i=1;i<=12;i++) T[i]=B;
    	read(nfish);
    	for(int i=1;i<=nfish;i++){ 
    		read(r);
    		for(int j=0;j<r;j++) read(rr[j]);
    		rr[r]=rr[0];
    		for(int j=1;j<=12;j++)
    			for(int g=0;g<n;g++)
    				T[j].a[g][rr[(j-1)%r+1]]=0;
    	}
    	T[0].init(n,n);
    	T[0].build();
    	for(int i=1;i<=12;i++) T[0]=T[0]*T[i];
    	S=T[0].fpow(k/12);
    	k=k%12;
    	for(int i=1;i<=k;i++) S=S*T[i];
    	cout<<S.a[st][en];
    	return 0;
    }
    

    Luogu P2233公交车路线

    题目
    其实是应该用矩阵的但是既然有好写的递推可以拿来水题那为什么不呢
    贴一个巨好写的递推:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 20
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    const int mod=1000;
    ll n;
    ll ans=0,b=1;
    
    int main(){
        read(n);
        if(n%2) {
            cout<<0<<endl;
            return 0;
        }
        for(int i=1;i<=n/2-1;i++){
            ans=2*ans+b;
            b+=ans;
            ans%=1000;b%=1000;
        }
        (ans*=2)%=1000;
        cout<<ans<<endl;
        return 0;
    }
    

    再贴一个矩乘正解:(来自线代神仙wsy_jim)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=10,Mod=1000;
    
    
    
    struct Matrix{
    	int m,n;
    	int a[N][N];
    	
    	inline void init(int _m=0,int _n=0){
    		m=_m;n=_n;
    		memset(a,0,sizeof a);
    	}
    	
    	inline Matrix operator * (Matrix B){
    		Matrix res;
    		res.init(m,B.n);
    		for(int i=1;i<=m;i++)
    			for(int j=1;j<=B.m;j++)
    				for(int k=1;k<=n;k++)
    					(res.a[i][j]+=a[i][k]*B.a[k][j])%=Mod;
    		return res;
    	}
    	
    	inline void id(){
    		for(int i=1;i<=m;i++) a[i][i]=1;
    	}
    	
    	inline Matrix fpow(int t){
    		Matrix res;
    		res.init(m,m);
    		res.id();
    		Matrix tmp=*this;
    		for(;t;t>>=1,tmp=tmp*tmp) if(t&1) res=res*tmp;
    		return res;
    	}
    };
    
    int n;
    
    int main(){
    	
    	cin>>n;
    	
    	if(n<=3){cout<<0;return 0;}
    	if(n==4){cout<<2;return 0;}
    	
    	Matrix x;
    	x.init(8,8);
    	x.a[1][2]=x.a[1][8]=x.a[2][1]=x.a[2][3]=x.a[3][2]=x.a[3][4]=x.a[4][3]=1;
    	x.a[4][5]=x.a[6][5]=x.a[6][7]=x.a[7][6]=x.a[7][8]=x.a[8][1]=x.a[8][7]=1;
    	
    	cout<<x.fpow(n).a[1][5];
    	
    	return 0;
    }
    

    再贴一个奇怪的DP:(来自Blueqwq)

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e7+10;
    const int mod=1000;
    inline int read(){
    	int x=0;bool f=false;char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')	f=true;
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    int n;
    int f[2][10];
    int main(){
    	n=read();
    	if(n&1){
    		puts("0");
    		return 0;
    	}
    	f[0][1]=1;
    	for(int i=1;i<=n;i++){
    		memset(f[i&1],0,sizeof f[i&1]);
    		for(int j=1;j<=8;j++){
    			if(j-1!=5) f[i&1][j]+=f[(i&1)^1][(j-1==0?8:j-1)];
    			if(j+1!=5) f[i&1][j]+=f[(i&1)^1][(j+1==9?1:j+1)];
    			f[i&1][j]%=mod;
    		}
    	} 
    	printf("%d",f[n&1][5]);
    	return 0;
    }
    
  • 相关阅读:
    我眼中的DevOps
    Jenkins常用插件介绍之权限控制插件Role-based Authorization Strategy
    sql查询一个班级中总共有多少人以及男女分别多少人
    win8 图片等路径
    WPF 设置TextBox为空时,背景为文字提示。
    WCF服务发布
    win8 摄像
    oracle 删除主键
    oracle 数据库连接
    oracle 创建用户表
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14413978.html
Copyright © 2011-2022 走看看