BZOJ1009: [HNOI2008]GT考试
2018-01-20 15:07
357 查看
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4474 Solved: 2763
[Submit][Status][Discuss]
Description
阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为
0
Input
第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.Sample Input
4 3 100111
Sample Output
81HINT
Source
【题解】不妨设dp[i][j]表示前i个字符,后缀有j个匹配上了,其余的没有匹配上
他们说做多了AC自动机上DP就能想出这个状态。。
可我还没写过AC自动机的题
预处理a[i][j]表示长度为i的前缀加上一个字符到达长度为j的前缀的方案数
转移为dp[i][j] = Σdp[i-1][k] * a[k][j]
很明显的矩阵乘法
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <vector> #include <cmath> #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) inline void swap(int &a, int &b) { long long tmp = a;a = b;b = tmp; } inline void read(int &x) { x = 0;char ch = getchar(), c = ch; while(ch < '0' || ch > '9') c = ch, ch = getchar(); while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); if(c == '-') x = -x; } const int INF = 0x3f3f3f3f; const int MAXM = 30; int a[MAXM][MAXM], p[MAXM][MAXM], nxt[MAXM], k, n, m; char s[MAXM]; void kmp() { nxt[0] = -1; for(register int i = 1, j = -1;i < m;++ i) { while(j >= 0 && s[i] != s[j + 1]) j = nxt[j]; if(s[i] == s[j + 1]) ++ j; nxt[i] = j; } for(register int i = 0;i < m;++ i) for(register int j = '0';j <= '9';++ j) { int tmp = i - 1; while(tmp >= 0 && s[tmp + 1] != j) tmp = nxt[tmp]; if(s[tmp + 1] == j) ++ a[i][tmp + 2]; else ++ a[i][0]; } } int tmp[MAXM][MAXM], base[MAXM][MAXM]; void pow(int b) { for(register int i = 0;i < m;++ i) for(register int j = 0;j < m;++ j) base[i][j] = a[i][j]; for(;b;b >>= 1) { if(b & 1) { memset(tmp, 0, sizeof(tmp)); for(register int i = 0;i < m;++ i) for(register int j = 0;j < m;++ j) for(register int q = 0;q < m;++ q) { tmp[i][j] += a[i][q] * base[q][j] % k; if(tmp[i][j] >= k) tmp[i][j] -= k; } for(register int i = 0;i < m;++ i) for(register int j = 0;j < m;++ j) a[i][j] = tmp[i][j]; } memset(tmp, 0, sizeof(tmp)); for(register int i = 0;i < m;++ i) for(register int j = 0;j < m;++ j) for(register int q = 0;q < m;++ q) { tmp[i][j] += base[i][q] * base[q][j] % k; if(tmp[i][j] >= k) tmp[i][j] -= k; } for(register int i = 0;i < m;++ i) for(register int j = 0;j < m;++ j) base[i][j] = tmp[i][j]; } } int main() { read(n), read(m), read(k);scanf("%s", s); kmp(); pow(n - 1); int sum = 0; for(register int i = 0;i < m;++ i) { sum += a[0][i]; if(sum >= k) sum -= k; } printf("%d", sum); return 0; }
BZOJ1009
相关文章推荐
- bzoj1009 [HNOI2008]GT考试(AC+矩乘优化dp)
- BZOJ 1009: [HNOI2008]GT考试【KMP上DP+矩阵快速幂
- BZOJ 1009: [HNOI2008]GT考试
- Bzoj1009: [HNOI2008]GT考试
- 【矩阵乘】【KMP】【HNOI 2008】【bzoj 1009】GT考试
- BZOJ1009:[HNOI2008]GT考试——题解
- BZOJ-1009-GT考试-HNOI2008
- 【BZOJ1009】【HNOI2008】GT考试
- bzoj 1009: [HNOI2008]GT考试(AC自动机+矩阵优化dp)
- [BZOJ1009][HNOI2008]GT考试(AC自动机+dp+矩阵优化)
- [BZOJ1009][HNOI2008]GT考试(KMP+DP+矩阵乘法)
- BZOJ 1009: [HNOI2008]GT考试
- BZOJ1009: [HNOI2008]GT考试
- BZOJ1009: [HNOI2008]GT考试
- bzoj1009 [HNOI2008]GT考试
- BZOJ1009 [HNOI2008]GT考试(KMP算法+矩阵加速dp)
- 【DP+矩阵优化】[HNOI2008][HYSBZ/BZOJ1009]GT考试
- BZOJ-1009-GT考试-HNOI2008
- BZOJ 1009:[HNOI2008]GT考试
- [BZOJ1009][HNOI2008]GT考试