BZOJ--1009(KMP,DP,矩阵快速幂)
2014-12-15 22:25:47
思路:这题写了我好久,主要是卡在根据KMP结果来构造矩阵上面。
如果用dp[i][j]表示用前i个字符匹配字串前j个字符
那么考虑用i->i+1的转移。
显然,如果考虑所有i+1位可能放的数字(0~9)
那么有:dp[i+1][j+1] += dp[i][j] //继续匹配下一个字符(j+1)
dp[i+1][0] += dp[i][j] //字串根本无法匹配
dp[i+1][1] += dp[i][j] //刚好能匹配字串的第一个字符
dp[i+1][P[j]+1] += dp[i][j] //根据KMP,如果i+1位置失效,那么往前找最近的匹配位置!
那么根据转移方程来构造矩阵,快速幂即可。(因为可以0匹配,所以KMP构造P数组的时候要注意下标起点(最好字串从1下标开始))
1 /************************************************************************* 2 > File Name: b1009.cpp 3 > Author: Natureal 4 > Mail: 564374850@qq.com 5 > Created Time: Mon 15 Dec 2014 08:32:47 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 typedef unsigned long long ull; 26 const int INF = 1 << 30; 27 28 int N,M,K; 29 int P[30]; 30 char s[30]; 31 32 struct Mx{ 33 int a[30][30]; 34 void clear(){ memset(a,0,sizeof(a));} 35 void stand(){ clear(); for(int i = 0; i < 20; ++i) a[i][i] = 1;} 36 Mx operator * (Mx b){ 37 Mx c; c.clear(); 38 for(int i = 0; i < 20; ++i) 39 for(int j = 0; j < 20; ++j) 40 for(int k = 0; k < 20; ++k){ 41 c.a[i][j] = (c.a[i][j] + a[i][k] * b.a[k][j]) % K; 42 } 43 return c; 44 } 45 }; 46 47 void Get_P(){ 48 P[1] = 0; 49 int j = 0; 50 for(int i = 2; i <= M; ++i){ 51 while(j > 0 && s[j + 1] != s[i]) j = P[j]; 52 if(s[j + 1] == s[i]) j++; 53 P[i] = j; 54 } 55 } 56 57 int main(){ 58 scanf("%d%d%d",&N,&M,&K); 59 scanf("%s",s + 1); 60 Get_P(); 61 Mx res,t; 62 t.clear(); 63 res.stand(); 64 //construct 枚举第i个字符为j 65 for(int i = 0; i < M; ++i){ 66 for(int j = 0; j < 10; ++j){ 67 int pos = i; 68 while(pos > 0 && s[pos + 1] - '0' != j) pos = P[pos]; 69 if(s[pos + 1] - '0' == j) pos++; 70 t.a[pos][i] = (t.a[pos][i] + 1) % K; 71 } 72 } 73 //matrix pow 74 while(N){ 75 if(N & 1) res = res * t; 76 t = t * t; 77 N >>= 1; 78 } 79 int ans = 0; 80 for(int i = 0; i < M; ++i) ans = (ans + res.a[i][0]) % K; 81 printf("%d\n",ans); 82 return 0; 83 } 84 85