3530: [Sdoi2014]数数

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 682  Solved: 364

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

【分析】

  这题AC自动机+数位DP。
  话说数位DP搞了我好久。主要是联系上AC自动机判病毒串的时候有点卡- -(脑子一片混乱
  dp方程:f[i][j]表示现在在点j,继续走i步(不经病毒点)的方案数。
  先把长度小于n的加入ans,我是for了一遍长度累加的(前缀0那里有点坑,so...)
  然后手动填与n长度相等的串,for一下,判断一下,累加一下,就好了。。 你懂的...

  

  主要部分:

  

手动填数部分:

  

  注意是不大于N。

完整代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 1600
#define Maxl 1600
#define Mod 1000000007 struct node
{
int fail,mark;
int son[];
}t[Maxn];int tot; int m,sl; void upd(int x)
{
t[x].mark=;
memset(t[x].son,,sizeof(t[x].son));
} char s[Maxl];
char ss[Maxn];
void read_trie()
{
scanf("%s",s+);
int len=strlen(s+);
int now=;
for(int i=;i<=len;i++)
{
int ind=s[i]-''+;
if(!t[now].son[ind])
{
t[now].son[ind]=++tot;
upd(tot);
}
now=t[now].son[ind];
if(i==len) t[now].mark=;
}
} queue<int > q;
void build_AC()
{
while(!q.empty()) q.pop();
q.push();
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=;i<=;i++)
{
if(t[x].son[i])
{
t[t[x].son[i]].fail=x?t[t[x].fail].son[i]:;
q.push(t[x].son[i]);
}
else t[x].son[i]=t[t[x].fail].son[i];
}
if(t[t[x].fail].mark) t[x].mark=;
}
} void init()
{
scanf("%s",ss+);
sl=strlen(ss+);
scanf("%d",&m);
tot=;upd();
for(int i=;i<=m;i++) read_trie();
build_AC();
} int check()
{
for(int i=;i<=sl;i++)
{
bool p=;
int now=;
for(int j=i;j>=;j--)
{
if(t[ t[now].son[ss[j]-''+] ].mark) {p=;break;}
now=t[now].son[ss[j]-''+];
}
if(!p) return i;
}
return ;
} int f[Maxn][Maxn];
void dp()
{
memset(f,,sizeof(f));
for(int i=;i<=tot;i++) f[][i]=;//走到i点,继续填0个数的方案 for(int i=;i<=sl;i++)
{
for(int j=;j<=tot;j++) if(!t[j].mark)
{
for(int k=;k<=;k++) if(!t[t[j].son[k]].mark)
f[i][j]=(f[i][j]+f[i-][t[j].son[k]])%Mod;
}
} int ans=;
if(sl!=)
{
for(int j=;j<=sl;j++)
for(int i=;i<=;i++) if(!t[t[].son[i]].mark)
ans=(ans+f[sl-j][t[].son[i]])%Mod;
} int now=;
bool ok=;
for(int i=sl;i>=;i--)
{
for(int k=;k<ss[sl-i+]-'';k++)//枚举第i位填的数
{
if(i==sl&&k==) continue;
if(t[t[now].son[k+]].mark) continue;
ans=(ans+f[i-][t[now].son[k+]])%Mod;
}
now=t[now].son[ss[sl-i+]-''+];
if(t[now].mark) {ok=;break;}
}
if(ok) ans=(ans+)%Mod;
if(sl==&&ss[]=='') ans=;
printf("%d\n",ans);
} int main()
{
init();
dp();
return ;
}

[HDU3530]

2016-07-14 10:51:01

【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)

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

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

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

  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. iTunes无法验证服务器“s.mzstatic.com.”的身份

    修改hosts文件,在里面添上一行 23.214.233.166 s.mzstatic.com

  2. ASP.NET MVC ajax提交 防止CSRF攻击

    //在View中 <script type="text/javascript"> @functions{ public string ToKenHeaderValue( ...

  3. jQuery获取radio选中项的值【转藏】

    <title></title> <script src="js/jquery-1.7.2.min.js"></script> < ...

  4. html 包含一个公共文件

    <SCRIPT> $(document).ready(function(){ $("#foo").load("top.html"); setTime ...

  5. Js 的常用方法:页面跳转,Session,类继承

    MyApp.Base = function () { } var basePrototype = MyApp.Base["prototype"]; //对象克隆方法 basePro ...

  6. asp.net - GridView根据linkButton值不同跳转不同页面

    一,当前页面中,前台界面的主要代码: <asp:TemplateField HeaderText="姓名"> <ItemTemplate> <!--根 ...

  7. jsp - java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver

    使用jsp连接数据库真的不那么容易,之前使用纯java连接sql Server 2008,都是很正常的,但是在使用jsp调用的时候,总是报错ClassNotFoundException.很郁闷 jar ...

  8. wamp使用方法【总】

    Apache与php配置:我们把php-5.2.9-Win32.zip解压到C盘根目录下,把文件夹名字改成PHP,这样方便一下. 1. 找到PHP目录下的“php.ini-dist”或者“php.in ...

  9. Spring Security Encryption三种加密方式

    Encryption One-way encryption       单项加密,客户端将要传递的值先加密(使用特定的加密方法),将原值和加密好的值传递过去,服务器端将原始数据也进行一次加密(两者加密 ...

  10. 逻辑回归:使用SGD(Stochastic Gradient Descent)进行大规模机器学习

    Mahout学习算法训练模型 mahout提供了许多分类算法,但许多被设计来处理非常大的数据集,因此可能会有点麻烦.另一方面,有些很容易上手,因为,虽然依然可扩展性,它们具有低开销小的数据集.这样一个 ...