【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
2016-07-14 10:48
477 查看
3530: [Sdoi2014]数数
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 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
203
2
3
14
Sample 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一下,判断一下,累加一下,就好了。。 你懂的...
主要部分:
#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[30]; }t[Maxn];int tot; int m,sl; void upd(int x) { t[x].mark=0; memset(t[x].son,0,sizeof(t[x].son)); } char s[Maxl]; char ss[Maxn]; void read_trie() { scanf("%s",s+1); int len=strlen(s+1); int now=0; for(int i=1;i<=len;i++) { int ind=s[i]-'0'+1; if(!t[now].son[ind]) { t[now].son[ind]=++tot; upd(tot); } now=t[now].son[ind]; if(i==len) t[now].mark=1; } } queue<int > q; void build_AC() { while(!q.empty()) q.pop(); q.push(0); while(!q.empty()) { int x=q.front();q.pop(); for(int i=1;i<=10;i++) { if(t[x].son[i]) { t[t[x].son[i]].fail=x?t[t[x].fail].son[i]:0; 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=1; } } void init() { scanf("%s",ss+1); sl=strlen(ss+1); scanf("%d",&m); tot=0;upd(0); for(int i=1;i<=m;i++) read_trie(); build_AC(); } int check() { for(int i=1;i<=sl;i++) { bool p=1; int now=0; for(int j=i;j>=1;j--) { if(t[ t[now].son[ss[j]-'0'+1] ].mark) {p=0;break;} now=t[now].son[ss[j]-'0'+1]; } if(!p) return i; } return 0; } int f[Maxn][Maxn]; void dp() { memset(f,0,sizeof(f)); for(int i=0;i<=tot;i++) f[0][i]=1;//走到i点,继续填0个数的方案 for(int i=1;i<=sl;i++) { for(int j=0;j<=tot;j++) if(!t[j].mark) { for(int k=1;k<=10;k++) if(!t[t[j].son[k]].mark) f[i][j]=(f[i][j]+f[i-1][t[j].son[k]])%Mod; } } int ans=0; if(sl!=1) { for(int j=2;j<=sl;j++) for(int i=2;i<=10;i++) if(!t[t[0].son[i]].mark) ans=(ans+f[sl-j][t[0].son[i]])%Mod; } int now=0; bool ok=1; for(int i=sl;i>=1;i--) { for(int k=0;k<ss[sl-i+1]-'0';k++)//枚举第i位填的数 { if(i==sl&&k==0) continue; if(t[t[now].son[k+1]].mark) continue; ans=(ans+f[i-1][t[now].son[k+1]])%Mod; } now=t[now].son[ss[sl-i+1]-'0'+1]; if(t[now].mark) {ok=0;break;} } if(ok) ans=(ans+1)%Mod; if(sl==1&&ss[1]=='0') ans=0; printf("%d\n",ans); } int main() { init(); dp(); return 0; }
[HDU3530]
2016-07-14 10:51:01
相关文章推荐
- 【荐】利用NAT、Host-Only双虚拟网卡,实现Virtual Box中CentOS5.x联网
- Singleton 多线程
- [POJ2104] K-th Number(区间K小数,主席树模板)
- 我对Java Serializable(序列化)的理解和总结
- tomcat启动出现:Caused by: java.net.UnknownHostException: zspr: 未知的名称或服务
- 静态、自适应、流式、响应式布局
- 搭建Tomcat8+ solr-5.5.1+zookeeper3.4.6集群及单机版
- mybatis绑定错误
- ABB机器人添加串口模块后无法使用的解决办法
- iOS 语音wav转amr amr转war三方库
- Android EditText得到和失去焦点时,自定义处理内容
- 理解HTTP session原理及应用
- 廖雪峰python学习笔记12.StringIO和BytesIO
- Spring 中的 LocalSessionFactoryBean和LocalContainerEntityManagerFactoryBean???
- 【poj2778-DNA Sequence】AC自动机+矩阵乘法
- 如何查看 Linux是32位还是64位?
- Java中<< ,>>
- sendRedirect与forward
- 获取第三方网站信息解析
- 几何学