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; }