原来的DP:
dp[i][j]表示长度为i的合法串,并且它的长度为j的后缀是给定串的长度为j的前缀。
转移:
i==0
dp[0][0] = 1 dp[0][1~m-1] = 0
i>=1
dp[i][0] = dp[i-1][0]*10-dp[i-1][m-1]
dp[i][1] = dp[i-1][0]-(a[m]==a[1])*dp[i-1][m-1]
dp[i][2] = dp[i-1][1]-(a[m-1~m]==a[1~2])*dp[i-1][m-1]
dp[i][3] = dp[i-1][2]-(a[m-2~m]==a[1~3])*dp[i-1][m-1]
...
dp[i][m-1] = dp[i-1][m-2]-(a[2~m]==a[1~m-1])*dp[i-1][m-1]
(a[i~j]==a[p~q]表示原串的[i,j]区间与[p,q]区间是否相等)
然后就是一般的矩阵求线性递推的东西了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /************************************************************** 2 Problem: 1009 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:48 ms 7 Memory:804 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 12 13 int n, m, mod; 14 int a[20]; 15 bool mat[20]; 16 17 struct Matrix { 18 int a[20][20]; 19 void make_zero() { 20 for( int i=0; i<m; i++ ) 21 for( int j=0; j<m; j++ ) 22 a[i][j] = 0; 23 } 24 void make_unit() { 25 for( int i=0; i<m; i++ ) { 26 for( int j=0; j<m; j++ ) 27 a[i][j] = 0; 28 a[i][i] = 1; 29 } 30 } 31 Matrix operator*( const Matrix & B ) const { 32 const Matrix & A = *this; 33 Matrix C; 34 C.make_zero(); 35 for( int i=0; i<m; i++ ) 36 for( int j=0; j<m; j++ ) 37 for( int k=0; k<m; k++ ) { 38 C.a[i][j] += A.a[i][k]*B.a[k][j]; 39 C.a[i][j]%=mod; 40 } 41 return C; 42 } 43 }; 44 45 void prep() { 46 for( int i=0; i<m-1; i++ ) { 47 mat[i] = true; 48 for( int j=0; j<=i; j++ ) 49 if( a[j]!=a[m-i-1+j] ) { 50 mat[i] = false; 51 break; 52 } 53 } 54 } 55 Matrix mpow( Matrix a, int b ) { 56 Matrix rt; 57 rt.make_unit(); 58 for( ; b; b>>=1,a=a*a ) 59 if( b&1 ) rt=rt*a; 60 return rt; 61 } 62 63 void work() { 64 Matrix a; 65 a.make_zero(); 66 a.a[0][0] = 10; 67 a.a[0][m-1] = -1; 68 for( int i=1; i<m; i++ ) { 69 a.a[i][i-1] = 1; 70 a.a[i][m-1] = -mat[i-1]; 71 } 72 a = mpow(a,n); 73 int ans = (a.a[0][0]%mod+mod)%mod; 74 printf( "%d\n", ans ); 75 } 76 77 int main() { 78 scanf( "%d%d%d", &n, &m, &mod ); 79 char ch; 80 while( scanf( "%[\n ]", &ch ) ); 81 for( int i=0; i<m; i++ ) { 82 scanf( "%c", &ch ); 83 a[i] = ch-'0'; 84 } 85 prep(); 86 work(); 87 }