• 【BZOJ 3530】【SDOI 2014】数数


    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[N][10], tot = 1, end[N];
    
    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[N], fail[N];
    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[N], c[N];
    int m, f1[N], f2[N], f3[N], f4[N], r[N];
    
    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
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    必备单词
    Vim
    Linux基础
    python链表操作详解
    冒泡和快速排序
    学员练车选课系统
    面试题
    获取resp:heads:content-disposition的filename
    记录springBoot启动报错(无脑型)
    springBoot+Vue搭建新项目(1)
  • 原文地址:https://www.cnblogs.com/abclzr/p/6306874.html
Copyright © 2020-2023  润新知