【SDOI2014】数数
2016-01-28 15:52
363 查看
【SDOI2014】数数
Description
[code]计算不大于N且不包含S中的数的个数。
Solution
首先计算一个不大于N的数,而且还有一些限制,很明显就是数位DP。一个字符串在另一个字符串集合中操作,很容易想到AC自动机。如果要做DP,首先有一个i表示从高位到低位,做到第i位。要在AC自动机中匹配,还要加一个j,表示当前在AC自动机中节点为j。然后还要一个经典,0或1,表示当前数位小于N或等于N。所以就要转移一个DP->f[i,j,0…1],很显然是f[i,j,0]转移到f[i+1,p,0],f[i,j,1]转移到f[i+1,p,0]或f[i+1,p,1],现在就要讨论p是什么。因为现在做到的是节点j,所以之前的已经匹配过了,所以假设第i+1为的数字为k,所以要转移到next[j,k]表示当前在AC自动机的节点为j,要接到下一个数字为k的点为next[j,k]可是是他的儿子或祖先或祖先的儿子。注意在转移的时候,如果它可以转移到AC自动机上的某一点,当时这一点是输入的字符串集合的某一末节点时,就转移或统计答案。
Code
[code]#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; const int mo=1000000007; queue<int> data; int i,j,k,l,t,n,m,ans,next[10000][10],num,tot,fail[100000]; int f[1300][1510][2],len; struct node{ int son[10]; bool biao; }trie[100000]; char s[10000],st[10000]; void ac_automation(){ int head=0,tail=1,x,i; data.push(0); while(!data.empty()){ x=data.front(); data.pop(); fo(i,0,9){ if(trie[x].son[i]){ int y=trie[x].son[i],z=fail[x]; while(z&&!trie[z].son[i]) z=fail[z]; if(x!=0)fail[y]=trie[z].son[i]; if (!trie[y].biao)trie[y].biao=trie[trie[z].son[i]].biao; data.push(trie[x].son[i]); } } } } int main(){ freopen("count.in","r",stdin); freopen("count.out","w",stdout); scanf("%s",s+1); scanf("%d",&n); fo(j,1,n){ scanf("%s",st+1); int len=strlen(st+1),x=0; fo(i,1,len){ if(!trie[x].son[st[i]-'0']){ trie[x].son[st[i]-'0']=++num; x=num; } else x=trie[x].son[st[i]-'0']; } trie[x].biao=1; } len=strlen(s+1); ac_automation(); fo(i,0,num){ fo(j,0,9){ int x=i; while(x&&!trie[x].son[j])x=fail[x]; if(trie[x].son[j])next[i][j]=trie[x].son[j]; } } f[1][next[0][s[1]-'0']][1]++; fo(i,1,s[1]-'0'-1){ f[1][next[0][i]][0]++; } fo(i,1,len-1){ fo(k,1,9) f[i+1][next[0][k]][0]++; fo(j,0,num){ if(trie[j].biao)continue; if(f[i][j][0]){ fo(k,0,9){ f[i+1][next[j][k]][0]=(f[i+1][next[j][k]][0]+f[i][j][0])%mo; } } if(f[i][j][1]){ fo(k,0,s[i+1]-'0'-1){ f[i+1][next[j][k]][0]=(f[i+1][next[j][k]][0]+f[i][j][1])%mo; } f[i+1][next[j][s[i+1]-'0']][1]=(f[i+1][next[j][s[i+1]-'0']][1]+f[i][j][1])%mo; } } } fo(i,0,num) if(!trie[i].biao) ans=(ans+f[len][i][0]+f[len][i][1])%mo; printf("%d\n",ans); }
相关文章推荐
- HTML meta标签总结与属性的使用介绍
- IIS Express
- 解决yum升级的问题“There was a problem importing one of the Python modules”
- JSON 解析(2)
- JSON 格式(1)
- 可模拟手机,导入apk即可
- 获取checkbox 的选中状态的id、checkbox的一些操作
- Spring Data JPA 的配置文件 已经数据库的状态
- 网站设置实体类属性的一种方式
- Tomcat性能调优-让小猫飞奔
- codeforces 620e
- QT Creator 如何将第三方库加入到环境内
- 技术人员怎样转型成为产品经理?
- gearmand工作原理
- iOS NSURLSession
- 关于类的静态函数和非静态函数 声明与定义的区别
- 非常好的Java反射例子
- Objective-C Runtime 运行时之四:Method Swizzling(转载)
- iptables 防火墙整理及简单应用
- android SurfaceHolder与SurfaceView对象介绍