CodeForces 107D

来源:互联网 发布:手动编程适用于 编辑:程序博客网 时间:2024/06/06 09:11

矩阵快速幂
写出dp方程
状态就是所有模数的余数值的所有情况

#include<cstdio>#include<iostream>#include<cstring>#include<vector>#include<algorithm>using namespace std;typedef __int64 LL;const int mod=12345;const int N=130;vector<int> ve[30];#define pb push_backint top,ww[N],sta[N];int ll[30],rr[30];void cp(int A[N][N],int B[N][N],int n){    for(int i=0;i<n;i++){        for(int j=0;j<n;j++){            A[i][j]=B[i][j];        }    }}int D[N][N];void _mul(int A[N][N],int B[N][N],int n){    memset(D,0,sizeof(D));    for(int i=0;i<n;i++){        for(int j=0;j<n;j++){            for(int k=0;k<n;k++){                D[i][j]+=A[i][k]*B[k][j]%mod;                D[i][j]%=mod;            }        }    }    cp(A,D,n);}int C[N][N];void _pow(int A[N][N],LL b,int n){    memset(C,0,sizeof(C));    for(int i=0;i<n;i++){        C[i][i]=1;    }    while(b){        if(b&1){            _mul(C,A,n);        }        _mul(A,A,n);        b/=2;    }    cp(A,C,n);}void fco(int aa[N],int i){    for(int j=top-1;j>=0;j--){        aa[j]=i/ww[j];        i%=ww[j];    }}int A[N][N],B[N][N];int aa[N];void getA(int co){    memset(A,0,sizeof(A));    for(int i=0;i<co;i++){        for(int j=0;j<26;j++)if(ve[j].size()){            if(ve[j][0]==1){                A[i][i]++;            }            else {                fco(aa,i);                for(int jj=ll[j];jj<=rr[j];jj++){                    aa[jj]++;aa[jj]%=sta[jj];                }                int ii=0;                for(int jj=0;jj<top;jj++){                    ii+=aa[jj]*ww[jj];                }                A[ii][i]++;            }        }    }}void getB(){    memset(B,0,sizeof(B));    for(int i=0;i<26;i++)if(ve[i].size()){        if(ve[i][0]==1){            B[0][0]++;        }        else {            int ans=0;            for(int j=ll[i];j<=rr[i];j++){                ans+=ww[j];            }            B[ans][0]++;        }    }}int geta(int co){    int ans=0;    for(int i=0;i<co;i++){        fco(aa,i);        int fg=1;        for(int j=0;j<26;j++)if(ve[j].size()&&ve[j][0]!=1){            int flag=0;            for(int jj=ll[j];jj<=rr[j];jj++){                if(aa[jj]==0){                    flag=1;break;                }            }            fg=flag;            if(!fg)break;        }        if(fg){            ans+=A[i][0];ans%=mod;        }    }    return ans;}int main(){    #ifdef DouBi    freopen("in.cpp","r",stdin);    #endif // DouBi    LL n;int c;    while(scanf("%I64d%d",&n,&c)!=EOF){        for(int i=0;i<26;i++){            ve[i].clear();        }        for(int i=0;i<c;i++){            char ss[2];int a;            scanf("%s%d",ss,&a);            ve[ss[0]-'A'].pb(a);        }        if(n==0){            printf("1\n");continue;        }        for(int i=0;i<26;i++){            sort(ve[i].begin(),ve[i].end());            ve[i].erase(unique(ve[i].begin(),ve[i].end()),ve[i].end());            //printf("%d\n",ve[i].size());        }        int co=1;        top=0;        for(int i=0;i<26;i++)if(ve[i].size()&&ve[i][0]!=1){            ll[i]=top;            for(int j=0;j<ve[i].size();j++){                sta[top]=ve[i][j];                ww[top]=co;                co*=ve[i][j];                top++;            }            rr[i]=top-1;        }        getA(co);        _pow(A,n-1,co);        getB();        _mul(A,B,co);        printf("%d\n",geta(co));    }    return 0;}
0 0
原创粉丝点击