[BZOJ3550] [Sdoi2014]数数
Description
我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。
Input
输入的第一行包含整数N。
接下来一行一个整数M,表示S中元素的数量。
接下来M行,每行一个数字串,表示S中的一个元素。
Output
输出一行一个整数,表示答案模109+7的值。
Sample Input
3
2
3
14
Sample Output
HINT
下表中l表示N的长度,L表示S中所有串长度之和。
1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500
在AC自动机上跑DP。
设$\large f[0/1][i][j]$表示填到第i位,匹配到自动机上第j个节点, 是否有限制的方案数。
然后$\large f[0][i][j]$是可以转移到$\large f[0][i+1][nxt[j][k]]$的。
$\large f[1][i][j]$在k不等于这一位的时候可以转移到$\large f[0][i+1][nxt[j][k]]$,
在等于这一位的时候转移到$\large f[1][i+1][nxt[j][k]]$。
要特判一下匹配到根节点时,如果正在填第一位,只能从$\large [1, n[1]]$中选择数转移,和上面类似,
如果不是在填第1位,则可以直接转移到$\large f[0][...][...]$。
注意如果一个节点是一个单词的结尾就不转移,自动机上的表示要沿着fail指针传递。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
#define mod 1000000007
#define reg register
char n[];
int m; int cnt;
int nxt[][], end[], fail[];
int f[][][];//是否有限制,正在填第i个位置,匹配到第j个点.
int ans; inline void Ins(string s)
{
int now = ;
int len = s.length();
for (reg int i = ; i < len ; i ++)
now = nxt[now][s[i]-''] > ? nxt[now][s[i]-''] : (nxt[now][s[i]-''] = ++cnt);
end[now] = ;
} inline void AC_Match()
{
queue <int> q;
for (reg int i = ; i <= ; i ++)
if (nxt[][i]) q.push(nxt[][i]);
while(!q.empty())
{
int x = q.front();q.pop();
for (reg int i = ; i <= ; i ++)
{
if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]), end[nxt[x][i]] |= end[nxt[fail[x]][i]];
else nxt[x][i] = nxt[fail[x]][i];
}
}
} signed main()
{
scanf("%s", n + );
scanf("%d", &m);
for (reg int i = ; i <= m ; i ++)
{
string x;
cin >> x;
Ins(x);
}
AC_Match();
int len = strlen(n + );
for (reg int i = ; i < len ; i ++)
{
for (reg int j = ; j <= cnt ; j ++)
{
if (f[][i][j]) {
for (reg int k = ; k <= ; k ++)
if (!end[nxt[j][k]]) (f[][i+][nxt[j][k]] += f[][i][j]) %= mod;
}
if (f[][i][j]) {
int up = n[i+] - '';
for (reg int k = ; k < up ; k ++)
if (!end[nxt[j][k]]) (f[][i+][nxt[j][k]] += f[][i][j]) %= mod;
if (!end[nxt[j][up]]) (f[][i+][nxt[j][up]] += f[][i][j]) %= mod;
}
if (j == )
{
if (i == ) {
int up = n[i+] - '';
for (reg int k = ; k < up ; k ++)
if (!end[nxt[j][k]]) (f[][i+][nxt[j][k]] += ) %= mod;
if (!end[nxt[j][up]]) (f[][i+][nxt[j][up]] += ) %= mod;
} else {
for (reg int k = ; k <= ; k ++)
if (!end[nxt[j][k]]) (f[][i+][nxt[j][k]] += ) %= mod;
}
}
}
}
for (reg int i = ; i <= cnt ; i ++)
(ans += (f[][len][i] + f[][len][i]) % mod) %= mod;
cout << ans << endl;
return ;
}
[BZOJ3550] [Sdoi2014]数数的更多相关文章
- 【BZOJ】【3530】【SDOI2014】数数
AC自动机/数位DP orz zyf 好题啊= =同时加深了我对AC自动机(这个应该可以叫Trie图了吧……出边补全!)和数位DP的理解……不过不能自己写出来还真是弱…… /************* ...
- BZOJ3530: [Sdoi2014]数数
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 322 Solved: 188[Submit][Status] ...
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 682 Solved: 364 Description 我们称一 ...
- BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]
3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...
- 「SDOI2014」数数 解题报告
「SDOI2014」数数 题目描述 我们称一个正整数 \(N\) 是幸运数,当且仅当它的十进制表示中不包含数字串集合 \(S\) 中任意一个元素作为其子串. 例如当 \(S=(\)22, 333, 0 ...
- 3530: [Sdoi2014]数数
3530: [Sdoi2014]数数 链接 分析: 对给定的串建立AC自动机,然后数位dp.数位dp的过程中,记录当前在AC自动机的哪个点上,保证不能走到出现了给定串的点. 代码: #include& ...
- [SDOI2014]数数 --- AC自动机 + 数位DP
[SDOI2014]数数 题目描述: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串. 例如当S=(22,333,0233)时,233是幸运数,2333 ...
- bzoj [Sdoi2014]数数 AC自动机上dp
[Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1264 Solved: 636[Submit][Status][Discu ...
- [Sdoi2014]数数[数位dp+AC自动机]
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 834 Solved: 434[Submit][Status][ ...
- [bzoj3530][Sdoi2014]数数_AC自动机_数位dp
数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...
随机推荐
- SqlServer 2014 还原数据库时提示:操作系统返回了错误5,,拒绝访问
场景 在进行数据库还原时提示: System.Data.SqlError:在对”“尝试”“时,操作系统返回了错误5(拒绝访问) 实现 第一种方案是修改要还原的数据库备份文件的权限. 找到备份文件右击属 ...
- 从MySQL到Hive,数据迁移就这么简单
使用Sqoop能够极大简化MySQL数据迁移至Hive之流程,并降低Hadoop处理分析任务时的难度. 先决条件:安装并运行有Sqoop与Hive的Hadoop环境.为了加快处理速度,我们还将使用Cl ...
- Linux下一键安装包的基础上安装SVN及实现nginx web同步更新
Linux下一键安装包的基础上安装SVN及实现nginx web同步更新 一.安装 1.查看是否安装cvs rpm -qa | grep subversion 2.安装 yum install sub ...
- 软件测试的分类&软件测试生命周期
软件测试的分类: 按测试执行阶段:单元测试.集成测试.系统测试.验收测试.(正式验收测试,Alpha 测试-内侧,Beta 测试-公测) 按测试技术分类:黑盒测试.白盒测试.灰盒测试 按测试对象是否运 ...
- c#通过Redis实现轻量级消息组件
最近在开发一个轻量级ASP.NET MVC开发框架,需要加入日志记录,邮件发送,短信发送等功能,为了保持模块的独立性,所以需要通过消息通信的方式进行处理,为了保持框架在部署,使用,二次开发过程中的简易 ...
- 站内搜索(ELK)之开篇
因工作需要,近期使用ELK搭建单位内部“站内搜索”,目前已将内部OA系统20余个流程的表单.附件的数据索引到elasticsearch中,包括打印复印流程.声像采集流程.远程文件发送.规章制度.内线电 ...
- Spring 梳理-JdbcTemplate简介
JdbcTemplate简介 Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中. JdbcTempla ...
- Kotlin学习系列(二)
IF表达式 if在kotlin可以当做表达式使用跟java的三元操作符类似: var max = if( a > b ) a else b if分支可以使用代码块,最后一个表达式是返回值: va ...
- 自定义TabLayout的Indicator
最近项目要使用类似TabLayout的控件,其实我感觉就是TabLayout只是换了一个Indicator,先说一说TabLayout这是Android Support Design的控件要使用的同学 ...
- Mysql高手系列 - 第18篇:mysql流程控制语句详解(高手进阶)
Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 这是Mysql系列第18篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符 ...