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

20
3
2
3
14

Sample Output

14

HINT

下表中l表示N的长度,L表示S中所有串长度之和。

1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500

Solution

一个挺简单的一个题……建出来$AC$自动机然后在上面直接跑数位$DP$就好了。只不过有点小地方需要注意。

用$DFS(zero,lim,pos,now)$是否有前导0,是否卡上界,第$pos$位,自动机上第$now$个点。

为什么要存前导0呢?我们可以发现有这么一个例子:

10

1

01

这个跑出来应该是10,然而不记前导零特判一下会跑出来9。这是因为当幸运串为01的时候我们会忽略前导0,所以是合法的。

只需要在$DFS$的时候特判一下,如果有前导0,且幸运数这一位选0,且$now$还在根节点,就让$now$停在根节点就好了。

建立AC自动机的时候,如果某个节点能够沿着fail指针跳到单词节点,那么这个节点也应当禁止通过……

自测一时爽

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define N (1509)
#define MOD (1000000007)
using namespace std; int sz,Son[N][],Fail[N],End[N];
int cnt,m,x,f[N][N],a[N],spc[N];
char n[N],s[N];
queue<int>q; void Insert(char s[])
{
int now=;
for (int i=,l=strlen(s); i<l; ++i)
{
int c=s[i]-'';
if (!Son[now][c]) Son[now][c]=++sz;
now=Son[now][c];
}
End[now]++;
} void Build_Fail()
{
for (int i=; i<=; ++i)
if (Son[][i]) q.push(Son[][i]);
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=; i<=; ++i)
{
if (!Son[now][i])
{
Son[now][i]=Son[Fail[now]][i];
continue;
}
Fail[Son[now][i]]=Son[Fail[now]][i];
q.push(Son[now][i]);
}
}
} int DFS(int zero,int lim,int pos,int now)
{
if (pos==) return ;
if (!zero && !lim && f[pos][now]!=-) return f[pos][now];
f[pos][now]=;
int up=lim?n[pos]-'':;
for (int i=; i<=up; ++i)
if (!End[Son[now][i]])
{
if (zero && !i && !now) (f[pos][now]+=DFS(zero,lim&&==up,pos-,))%=MOD;
else
{
int flag=,t=Son[now][i];
while (t)
{
if (End[t]) {flag=; break;}
t=Fail[t];
}
if (!flag) continue;
(f[pos][now]+=DFS(zero&&!i,lim&&i==up,pos-,Son[now][i]))%=MOD;
}
}
return f[pos][now];
} int main()
{
memset(f,-,sizeof(f));
scanf("%s%d",n+,&m); cnt=strlen(n+);
for (int i=; i<=m; ++i)
scanf("%s",s),Insert(s);
Build_Fail();
for (int i=,j=cnt; i<j; ++i,--j)
swap(n[i],n[j]);
printf("%d\n",DFS(,,cnt,)-);
}

BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)的更多相关文章

  1. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  2. 【JZOJ3624】【SDOI2014】数数(count) AC自动机+数位dp

    题面 100 容易想到使用AC自动机来处理禁忌子串的问题: 然后在自动机上数位dp,具体是: \(f_{i,j,0/1}\)表示填了\(i\)位,当前在自动机的第\(j\)个结点上,\(0\)表示当前 ...

  3. 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  4. BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)

    题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...

  5. BZOJ3530[Sdoi2014]数数——AC自动机+数位DP

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  6. BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]

    3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...

  7. [SDOI2014]数数 --- AC自动机 + 数位DP

    [SDOI2014]数数 题目描述: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串. 例如当S=(22,333,0233)时,233是幸运数,2333 ...

  8. P3311 [SDOI2014]数数 AC自动机+数位DP

    题意 给定一个正整数N和n个模式串,问不大于N的数字中有多少个不包含任意模式串,输出对\(1e^9+7\)取模后的答案. 解题思路 把所有模式串都加入AC自动机,然后跑数位DP就好了.需要注意的是,这 ...

  9. HDU-4518 吉哥系列故事——最终数 AC自动机+数位DP

    题意:如果一个数中的某一段是长度大于2的菲波那契数,那么这个数就被定义为F数,前几个F数是13,21,34,55......将这些数字进行编号,a1 = 13, a2 = 21.现给定一个数n,输出和 ...

随机推荐

  1. Winform 常用的方法

    一,Winform 如何内嵌窗体 1,判断窗体中是否以还有内嵌窗体 private void ClosePreForm() { foreach (Control item in this.spCont ...

  2. [日常] Linux使用diff来比较目录

    Linux diff比较两个目录的不同: diff dir1 dir2  -urNaq -a  --text  Treat all files as text. -u  -U NUM  --unifi ...

  3. 悟空模式-java-单例模式

    [那座山,正当顶上,有一块仙石.其石有三丈六尺五寸高,有二丈四尺围圆.三丈六尺五寸高,按周天三百六十五度:二丈四尺围圆,按政历二十四气.上有九窍八孔,按九宫八卦.四面更无树木遮阴,左右倒有芝兰相衬.盖 ...

  4. Unity之使用技巧记录

    A:写了个死循环Unity无响应崩溃了怎么办? Q::到文件夹里找到刚刚写的脚本,把错误的代码屏蔽掉,再回到Unity

  5. 不同CSS布局实现与文字鼠标选择的可用性——张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=2401 一.文字选择的 ...

  6. UBuntu安装配置记录

    记得是06年左右第一次安装的 Linux,当时是下载的 Fedora镜像,版本已经记不清了,在商业街的电脑维修店刻的盘,回来后兴冲冲地和XP一起安装的双系统.其实就是直接的体验了一把,只是看了看X-W ...

  7. 关于Datagridview控件用法的一些总结

    一.引言 Datagridview控件在winform开发中还是比较常用,一般的数据库系统都会使用它,但是想要友好的展示数据,形成良好的用户界面,那么就要对c#库中默认的Datagridview设置进 ...

  8. Less与Sass框架

    一.Less语法 1.变量声明: @变量名:变量值; @newHeight:20px; 2.调用变量: .box { width: @newHeight; height: @newHeight; } ...

  9. div+css模拟select下拉框

    <!DOCTYPE html><html ><head lang="zh"> <meta http-equiv="Content ...

  10. Flutter的教程:ListView

    本文学习一下列表widget,是最常见的需求 在Flutter中,用ListView来显示列表项,支持垂直和水平方向展示,通过一个属性我们就可以控制其方向 1.水平的列表 2.垂直的列表 3.数据量非 ...