bzoj1009: [HNOI2008]GT考试

思路:设f[i][j]表示前i位后j位与不吉利串前j位相同的方案数,然后f[i][j]+=f[i-1][k]*trans[k][j],trans[k][j]表示串s后k位与不吉利串前k位相同,添加一个字符后后j位与不吉利串前j位相同的方案数,显然这个矩阵是可以用kmp求的,然后因为只能由i转移到i+1,且转移矩阵是一定的,于是可以用矩阵乘法快速幂优化dp即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxm 25
 
int n,m,p;
int next[maxm];
char s[maxm];
 
struct matrix{
    int a[maxm][maxm];
    void clear(){memset(a,0,sizeof(a));}
    void initialize(){clear();for (int i=0;i<m;i++) a[i][i]=1;}
}trans;
 
void getnext(){
    int len=strlen(s+1);next[1]=0;
    for (int i=2,j=0;i<=len;i++){
        while (j&&s[j+1]!=s[i]) j=next[j];
        if (s[j+1]==s[i]) j++;
        next[i]=j;
    }
}
 
void gettrans(){
    for (int i=0;i<m;i++)
        for (int j=0;j<=9;j++){
            int tmp=i;
            while (tmp && (s[tmp+1]-'0')!=j) tmp=next[tmp];
            if ((s[tmp+1]-'0')==j) trans.a[i][tmp+1]++,trans.a[i][tmp+1]%=p;
            else trans.a[i][0]++,trans.a[i][0]%=p;
        }
}
 
matrix mul(matrix a,matrix b){
    matrix c;c.clear();
    for (int i=0;i<m;i++)
        for (int j=0;j<m;j++)
            for (int k=0;k<m;k++)
                c.a[i][k]=(c.a[i][k]+a.a[i][j]*b.a[j][k]%p)%p;
    return c;
}
 
matrix power(matrix a,int k){
    matrix x;x.initialize();
    for (;k;k>>=1,a=mul(a,a)) if (k&1) x=mul(x,a);
    return x;
}
 
int main(){
    scanf("%d%d%d",&n,&m,&p);
    scanf("%s",s+1);
    getnext();
    gettrans();
    matrix tmp=power(trans,n),ans;ans.clear(),ans.a[0][0]=1;int t=0;
    ans=mul(ans,tmp);
    for (int i=0;i<m;i++) t=(t+ans.a[0][i])%p;
    printf("%d\n",t);
    return 0;
}

 

posted @ 2016-10-28 11:23  DUXT  阅读(210)  评论(1编辑  收藏  举报