您的位置:首页 > 其它

【BZOJ 3530】【SDOI 2014】数数

2017-01-19 15:39 441 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=3530

上午gty的测试题,爆0了qwq

类似文本生成器那道题,把AC自动机的转移建出来,准确地说建出了一个Trie图,然后在上面dp就可以了。

这道题因为有小于等于n的限制,所以要用类似数位dp的方法,记录卡不卡上界两个状态来转移。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1203;

int ch
[10], tot = 1, end
;

void insert(char *s) {
int len = strlen(s), x, tmp = 1, f;
for (int i = 0; i < len; ++i) {
x = s[i] - '0';
if (ch[tmp][x]) tmp = ch[tmp][x];
else tmp = ch[tmp][x] = ++tot;
}
end[tmp] = 1;
}

int qu
, fail
;
void BFS() {
int x, f, v, p = 0, q = 1; qu[1] = 1;
while (p != q) {
x = qu[++p];
for (int i = 0; i <= 9; ++i)
if (v = ch[x][i]) {
f = fail[x];
while (f && ch[f][i] == 0) f = fail[f];
fail[v] = f ? ch[f][i] : 1;
qu[++q] = v;
}
}
for (int i = 1; i <= q; ++i) {
x = qu[i];
for (int i = 0; i <= 9; ++i)
if (!ch[x][i])
ch[x][i] = ch[fail[x]][i];
}
}

char s
, c
;
int m, f1
, f2
, f3
, f4
, r
;

const int p = 1000000007;

int main() {
scanf("%s", s + 1);
scanf("%d", &m);
for (int i = 1; i <= m; ++i) {
scanf("%s", c);
insert(c);
}
for (int i = 0; i < 10; ++i) if (ch[1][i] == 0) ch[1][i] = ++tot;
BFS();
int *pre0 = f1, *pre1 = f2, *now0 = f3, *now1 = f4;
int len = strlen(s + 1);
for (int i = 1; i <= len; ++i) r[i] = s[i] - '0';
for (int tmp = 1; tmp <= len; ++tmp) {
swap(pre0, now0); swap(pre1, now1);
memset(now0, 0, sizeof(int) * (tot + 1));
memset(now1, 0, sizeof(int) * (tot + 1));
if (tmp == 1) {
if (end[ch[1][r[tmp]]] == 0)
(++now1[ch[1][r[tmp]]]) %= p;
for (int i = r[tmp] - 1; i >= 1; --i)
if (end[ch[1][i]] == 0)
(++now0[ch[1][i]]) %= p;
} else {
for (int i = 9; i >= 1; --i)
if (end[ch[1][i]] == 0)
(++now0[ch[1][i]]) %= p;
}
for (int i = 2; i <= tot; ++i) {
for (int j = 0; j < 10; ++j)
if (end[ch[i][j]] == 0)
(now0[ch[i][j]] += pre0[i]) %= p;
if (end[ch[i][r[tmp]]] == 0)
(now1[ch[i][r[tmp]]] += pre1[i]) %= p;
for (int j = r[tmp] - 1; j >= 0; --j)
if (end[ch[i][j]] == 0)
(now0[ch[i][j]] += pre1[i]) %= p;
}
}

int ans = 0;
for (int i = 1; i <= tot; ++i) {
ans = (ans + now0[i]) % p;
ans = (ans + now1[i]) % p;
}
printf("%d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: