【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 682 Solved: 364Description
我们称一个正整数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
14Sample Output
14HINT
下表中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)的更多相关文章
- 【JZOJ3624】【SDOI2014】数数(count) AC自动机+数位dp
题面 100 容易想到使用AC自动机来处理禁忌子串的问题: 然后在自动机上数位dp,具体是: \(f_{i,j,0/1}\)表示填了\(i\)位,当前在自动机的第\(j\)个结点上,\(0\)表示当前 ...
- 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp
题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...
- BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)
题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...
- BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]
3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...
- BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)
Description 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3 ...
- BZOJ3530[Sdoi2014]数数——AC自动机+数位DP
题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...
- [SDOI2014]数数 --- AC自动机 + 数位DP
[SDOI2014]数数 题目描述: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串. 例如当S=(22,333,0233)时,233是幸运数,2333 ...
- P3311 [SDOI2014]数数 AC自动机+数位DP
题意 给定一个正整数N和n个模式串,问不大于N的数字中有多少个不包含任意模式串,输出对\(1e^9+7\)取模后的答案. 解题思路 把所有模式串都加入AC自动机,然后跑数位DP就好了.需要注意的是,这 ...
- HDU-4518 吉哥系列故事——最终数 AC自动机+数位DP
题意:如果一个数中的某一段是长度大于2的菲波那契数,那么这个数就被定义为F数,前几个F数是13,21,34,55......将这些数字进行编号,a1 = 13, a2 = 21.现给定一个数n,输出和 ...
随机推荐
- iTunes无法验证服务器“s.mzstatic.com.”的身份
修改hosts文件,在里面添上一行 23.214.233.166 s.mzstatic.com
- ASP.NET MVC ajax提交 防止CSRF攻击
//在View中 <script type="text/javascript"> @functions{ public string ToKenHeaderValue( ...
- jQuery获取radio选中项的值【转藏】
<title></title> <script src="js/jquery-1.7.2.min.js"></script> < ...
- html 包含一个公共文件
<SCRIPT> $(document).ready(function(){ $("#foo").load("top.html"); setTime ...
- Js 的常用方法:页面跳转,Session,类继承
MyApp.Base = function () { } var basePrototype = MyApp.Base["prototype"]; //对象克隆方法 basePro ...
- asp.net - GridView根据linkButton值不同跳转不同页面
一,当前页面中,前台界面的主要代码: <asp:TemplateField HeaderText="姓名"> <ItemTemplate> <!--根 ...
- jsp - java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
使用jsp连接数据库真的不那么容易,之前使用纯java连接sql Server 2008,都是很正常的,但是在使用jsp调用的时候,总是报错ClassNotFoundException.很郁闷 jar ...
- wamp使用方法【总】
Apache与php配置:我们把php-5.2.9-Win32.zip解压到C盘根目录下,把文件夹名字改成PHP,这样方便一下. 1. 找到PHP目录下的“php.ini-dist”或者“php.in ...
- Spring Security Encryption三种加密方式
Encryption One-way encryption 单项加密,客户端将要传递的值先加密(使用特定的加密方法),将原值和加密好的值传递过去,服务器端将原始数据也进行一次加密(两者加密 ...
- 逻辑回归:使用SGD(Stochastic Gradient Descent)进行大规模机器学习
Mahout学习算法训练模型 mahout提供了许多分类算法,但许多被设计来处理非常大的数据集,因此可能会有点麻烦.另一方面,有些很容易上手,因为,虽然依然可扩展性,它们具有低开销小的数据集.这样一个 ...