【DP+矩阵优化】[HNOI2008][HYSBZ/BZOJ1009]GT考试

来源:互联网 发布:ssh 端口修改 编辑:程序博客网 时间:2024/06/04 19:51

题目链接

分析

fi,j表示匹配计算到准考证第i位,后缀最大可以匹配不吉利数字的前j位

fi,j=kA1....AkbAjfi1,kcntb(0b9,cntb使A1....AkbAjb)

注:空串是任何字符串的字串

根据这个递推公式,即可计算出答案,但是直接做显然会超时。
用矩阵快速幂进行优化即可。

代码

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define MAXM 20int n,m,k,cir,ans;struct matrix{    int a[MAXM+1][MAXM+1];    matrix(int n){        memset(a,0,sizeof a);        for(int i=0;i<n;i++)            a[i][i]=1;    }    matrix(){        memset(a,0,sizeof a);    }    matrix operator*(const matrix &b)const{        matrix c;        int i,j,l;        for(i=0;i<m;i++)            for(j=0;j<m;j++)                for(l=0;l<m;l++)                    c.a[i][j]=(c.a[i][j]+a[i][l]*b.a[l][j])%k;        return c;    }    void operator*=(const matrix &b){        *this=*this*b;    }}a;char x[MAXM+10];void Read(int &x){    char c;    while(c=getchar(),c!=EOF)        if(c>='0'&&c<='9'){            x=c-'0';            while(c=getchar(),c>='0'&&c<='9')                x=x*10+c-'0';            ungetc(c,stdin);            return;        }}void read(){    Read(n),Read(m),Read(k);    scanf("%s",x+1);}matrix quick_pow(matrix c,int b){    matrix ret(m),a(c);    while(b){        if(b&1)            ret*=a;        a*=a;        b>>=1;    }    return ret;}void solve(){    int i,j,l,y;    for(i=0;i<m;i++){        for(j='0';j<='9';j++){            for(l=i+1;l;l--){                if(x[l]==j){                    for(y=0;y<l-1;y++)                        if(x[l-y-1]!=x[i-y])                            break;                    if(y==l-1)                        break;                }            }            a.a[i][l]++;        }    }    a=quick_pow(a,n);    for(i=0;i<m;i++)        ans=(ans+a.a[0][i])%k;}int main(){    read();    solve();    printf("%d\n",ans);}
0 0