bzoj 1009 DP 矩阵优化

 

原来的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]区间是否相等)

 

然后就是一般的矩阵求线性递推的东西了。

 

 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 }
View Code

 

posted @ 2015-02-18 13:56  idy002  阅读(155)  评论(0编辑  收藏  举报