kmp还得 加强
/************************************************************** Problem: 1009 User: lxy8584099 Language: C++ Result: Accepted Time:56 ms Memory:832 kb ****************************************************************/ /* dp+kmp+矩阵加速 先把dp打正确再说。 f(i,j) 表示前i个字符 最后j个和A中前j和相同 所有的方案数 go(i,j)表示 从已匹配好的i个字符后面 加上一个字符而转到匹配 j 个字符的方案数 f(i,j) = sigma f(i-1,k) +go(k,j) ( 0<=k<m ) 因为不能相同 k不取 m n^2预处理 go 然后是矩阵加速 初始矩阵是 相当于 dp[0][0]=1 f.mat[0][0]=1; 矩阵横向排列 加速矩阵正好就是 go 数组 kmp讲究 我还是没搞懂,, */ #include<cstdio> #include<cstring> using namespace std; const int N=35; int nxt[N],n,m,MOD,ans; char s[N]; struct Mat { int mat[N][N]; Mat() {memset(mat,0,sizeof(mat));} Mat operator * (Mat b) { Mat a=*this,c; for(int i=0;i<m;i++) for(int j=0;j<m;j++) { for(int k=0;k<m;k++) (c.mat[i][j]+=a.mat[i][k]*b.mat[k][j])%=MOD; } return c; } Mat operator ^ (int b) { Mat a=*this,c; for(int i=0;i<m;i++) c.mat[i][i]=1; for(;b;b>>=1,a=a*a) if(b&1) c=c*a; return c; } }f,go; int main() { scanf("%d%d%d",&n,&m,&MOD); scanf("%s",s); for(int i=1,j=0;i<m;i++) { j=nxt[i]; while(j&&s[i]!=s[j]) j=nxt[j]; if(s[i]==s[j]) j++; nxt[i+1]=j; } // for(int i=1,j=0;i<m;i++) // { // while(j&&s[i+1]!=s[j+1]) j=nxt[j]; // if(s[i+1]==s[j+1]) j++; // nxt[i+1]=j; // } for(int i=0;i<m;i++) for(int j='0';j<='9';j++) { int k=i; while(k&&s[k]!=j) k=nxt[k]; if(s[k]==j) k++; go.mat[i][k]++; } f.mat[0][0]=1; go=go^n; f=f*go; for(int i=0;i<m;i++) (ans=ans+f.mat[0][i])%=MOD; printf("%d\n",ans); return 0; }