矩阵快速幂基础

这里放一下矩阵快速幂的模板.

首先我们怎样记得转移矩阵的行列数呢,我么用手比划一下,先横,再竖着.为答案矩阵的一个元素,

所以第一个矩阵的列数与转移矩阵的横数相等,转移矩阵的列数与答案矩阵的列数相等...

205. 斐波那契

    #include<bits/stdc++.h>
    #define db double
    #define ll long long
    #define reg register
    #define pb(x) push_back(x)
    #define fup(i,x,y) for(reg int i=x;i<=y;++i)
    #define fdw(i,x,y) for(reg int i=x;i>=y;--i)
    using namespace std;
    const int mod=10000;
    int n;
    struct wy
    {
        ll a[5][5];
        wy(){memset(a,0,sizeof(a));}
        inline void clear ()
        {
            memset(a,0,sizeof(a));
        }
        wy friend operator *(wy a,wy b) 
        {
            wy c;
            fup(i,1,2) fup(j,1,2) fup(k,1,2) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
            return c;
        }
        wy friend operator ^(wy a,ll y)
        {
            wy c;
            fup(i,1,2) c.a[i][i]=1;
            while(y)
            {
                if(y&1) c=c*a;
                y>>=1;
                a=a*a;
             }
             return c;
        } 
    }A,B,C;
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        B.a[1][1]=0;B.a[1][2]=1;
        B.a[2][1]=1;B.a[2][2]=1;
        while(1)
        {
            n=read();
            if(n==-1) break;
            if(n<=2) 
            {
                if(n==0) puts("0");
                else puts("1");
                continue;
            }
            A.clear();
            A.a[1][1]=1;A.a[1][2]=1;
            C=B^(n-2);
            A=A*C;
            printf("%lld\n",A.a[1][2]);
        }
        return 0;
    }
    
View Code

 206. 石头游戏

注意判断边界..

#include<bits/stdc++.h>
#define db double
#define ll long long
#define reg register
#define pb(x) push_back(x)
#define fup(i,x,y) for(reg int i=x;i<=y;++i)
#define fdw(i,x,y) for(reg int i=x;i>=y;--i)
using namespace std;
int l=64,n,m,t,act;
int d[10][10],len[20];
char st[20][10];
struct wy
{
    ll a[70][70];
    wy(){memset(a,0,sizeof(a));}
    inline void dan()
    {
        memset(a,0,sizeof(a));
        fup(i,0,l) a[i][i]=1;
    }
    wy friend operator *(wy a,wy b)
    {
        wy c;
        fup(i,0,l) fup(j,0,l) fup(k,0,l) c.a[i][j]=c.a[i][j]+a.a[i][k]*b.a[k][j];
        return c;
    }
    wy friend operator ^(wy a,ll y)
    {
        wy c;
        fup(i,0,l) c.a[i][i]=1;
        while(y)
        {
            if(y&1) c=c*a;
            y>>=1;
            a=a*a;
        }
        return c;
    }
}A[70],B,C;    
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}
int main()
{
    n=read();m=read();t=read();act=read();
    fup(i,1,n) fup(j,1,m) 
    {
        char c;cin>>c;
        d[i][j]=c-'0';
    }
    fup(i,0,act-1) scanf("%s",st[i]+1),len[i]=strlen(st[i]+1);
    fup(k,1,60)
    {
        A[k].a[0][0]=1;
        fup(i,1,n) fup(j,1,m)
        {
            int id=(i-1)*m+j;
            int op=k%len[d[i][j]]?(k%len[d[i][j]]):(len[d[i][j]]);
            if(st[d[i][j]][op]>='0'&&st[d[i][j]][op]<='9')
            {
                A[k].a[0][id]=st[d[i][j]][op]-'0';
                A[k].a[id][id]=1;
            }
            else if(st[d[i][j]][op]=='D') continue;
            else 
            {
                if(st[d[i][j]][op]=='N'&&i!=1) A[k].a[id][(i-2)*m+j]=1;
                else if(st[d[i][j]][op]=='W'&&j!=1) A[k].a[id][id-1]=1;
                else if(st[d[i][j]][op]=='S'&&i!=n) A[k].a[id][i*m+j]=1;
                else if(st[d[i][j]][op]=='E'&&j!=m) A[k].a[id][id+1]=1;
            }
        }
    }
    C.dan();
    fup(i,1,60) C=C*A[i];
    C=C^(t/60);
    B.a[1][0]=1;
    B=B*C;
    fup(i,1,t%60) 
    {
        B=B*A[i];
    }
    ll ans=0;
    fup(i,1,n*m) ans=max(ans,B.a[1][i]);
    printf("%lld",ans);
    return 0;
}
View Code

 

[TJOI2017]可乐

//又是一眼看过去就没有思路的题...
//算了,还是慢慢来吧,一点一点看这道题..
//首先看到这道题的第一印象,dp嗯..
//可后来发现由于好像有环...好像不怎么行,但还是得抱着人有多大胆,地有多大产的思想试试.
//我们设f[i][j]表示前j秒到达i的方案数...f[i][j]+=f[k][j-1]..(k->i). 
//但好像有环,且原地不动和自爆怎么搞...不行,看来dp不能用这种形式瞎搞,思考这道题的本质.
//题目给定无向图,求在t内的所有方案数....
//由于最开始处于1号点,实际上就是求1号点在t时间内到其他点的方案数. 
//我们思考如何求到其他点的方案数...我们发现由于环的缘故我们不能简单的用上一个dp类似的状态求解.
//这要求我们增加状态,设f[i][j]表示i到j的方案数.显然f[i][j]=f[i][k]*f[k][j].
//(这样思考,我们由于无法确定从哪过来的所以这样记录下来.表示前t秒从i到j的方案数.所以不用管t秒是如何分配的)
//之后思考原地不动和爆炸如何搞定.原地不动就是待在原地,那连个自环即可.爆炸就是我们新建一个虚拟节点,只从各个节点
//向它连边即可,这样就能达到爆炸就无法复原的效果了.
//之后由于时间的限制,我们无法快速求解上面的dp,但却能惊奇的发现,好像矩阵乘法啊.....
//于是就愉快地写题了. 
#include<bits/stdc++.h>
#define db double
#define ll long long
#define reg register
#define pb(x) push_back(x)
#define fup(i,x,y) for(reg int i=x;i<=y;++i)
#define fdw(i,x,y) for(reg int i=x;i>=y;--i)
using namespace std;
const int N=110,mod=2017;
int n,m,t;
struct wy
{
    int a[N][N];
    wy(){memset(a,0,sizeof(a));}
    wy friend operator *(wy a,wy b)
    {
        wy c;
        fup(i,0,n) fup(j,0,n) fup(k,0,n) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
        return c;
    }
    wy friend operator ^(wy a,int y)
    {
        wy c;
        fup(i,0,n) c.a[i][i]=1;
        while(y)
        {
            if(y&1) c=c*a;
            y>>=1;
            a=a*a;
        }
        return c;
    }
}C;
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}
int main()
{
    freopen("1.in","r",stdin);
    n=read();m=read();
    fup(i,1,m)
    {
        int x=read(),y=read();
        C.a[x][y]=1;C.a[y][x]=1;
    }
    t=read();
    fup(i,0,n) C.a[i][0]=1,C.a[i][i]=1;
    C=C^t;
    int ans=0;
    fup(i,0,n) ans=(ans+C.a[1][i])%mod;
    printf("%d",ans);
    return 0;
}
View Code

 

P5175 数列

#include<bits/stdc++.h>
#define db double
#define ll long long
#define reg register
#define pb(x) push_back(x)
#define rep(i,x,y) for(reg int i=x;i<=y;++i)
#define fdw(i,x,y) for(reg int i=x;i>=y;--i)
using namespace std;
const int mod=1e9+7;
ll T,n,a1,a2,x,y; 
struct wy
{
    ll a[5][5];
    wy() {memset(a,0,sizeof(a));}
    inline void clear()    {memset(a,0,sizeof(a));}
    wy friend operator *(wy a,wy b)
    {
        wy c;
        rep(i,1,4) rep(j,1,4) rep(k,1,4) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
        return c;
    }
    wy friend operator ^(wy a,ll y)
    {
        wy c;
        rep(i,1,4) c.a[i][i]=1;
        while(y)
        {
            if(y&1) c=c*a;
            y>>=1;
            a=a*a;
        }
        return c;
    } 
}A,B;
inline ll read()
{
    ll x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}
int main()
{
    //freopen("1.in","r",stdin);
    T=read();
    while(T--)
    {
        n=read();a1=read();a2=read();x=read();y=read();
        if(n==1) printf("%lld\n",a1*a1%mod);
        else if(n==2) printf("%lld\n",(a1*a1%mod+a2*a2%mod)%mod);
        else 
        {
            A.clear();B.clear();
            A.a[1][1]=a1*a1%mod;A.a[1][2]=a2*a2%mod;A.a[1][3]=a1*a2%mod;A.a[1][4]=(a1*a1%mod+a2*a2%mod)%mod;
            B.a[1][1]=0;B.a[1][2]=y*y%mod;B.a[1][3]=0;B.a[1][4]=y*y%mod;
            B.a[2][1]=1;B.a[2][2]=x*x%mod;B.a[2][3]=x;B.a[2][4]=x*x%mod;
            B.a[3][1]=0;B.a[3][2]=2*x*y%mod;B.a[3][3]=y;B.a[3][4]=2*x*y%mod;
            B.a[4][1]=0;B.a[4][2]=0;B.a[4][3]=0;B.a[4][4]=1;
            B=B^(n-2);
            A=A*B;
            printf("%lld\n",A.a[1][4]);
        }    
    }
    return 0;
}
View Code

 

posted @ 2020-04-17 16:07  逆天峰  阅读(167)  评论(0编辑  收藏  举报
作者:逆天峰
出处:https://www.cnblogs.com/gcfer//