【SDOI2014】数数
2016-04-13 20:56
363 查看
Description
求1~N中不含数字串集合S中的任意一个的数字的数量。数字串可以有前导0,少于位数不用补0.
字符串集合中有M个串,字符集总长为L。
|N|<=1200,M<=100,L<=1500
Solution
AC自动机上DP。设Fi,j,up,zero表示当前到第i位,AC自动机走到j这个节点,有没有爆上界,是否在算前导0.
其实最后一维可以不要,%各位大犇,蒟蒻不会。
随便乱搞就好了。
Code
#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define N 2005 #define mo 1000000007 #define ll long long using namespace std; struct note{ int son[10],bz,next; }trie ; int n,tot,d ; ll ans,f [2][2]; char s ,st ; void makefail() { for(int i=0,j=1;i<j;) { int x=d[++i]; fo(k,0,9) if (trie[x].son[k]) { int y=trie[x].son[k]; if (x) { int z=trie[x].next; while (z&&!trie[z].son[k]) z=trie[z].next; trie[y].next=trie[z].son[k]; } if (!trie[y].bz) trie[y].bz=trie[trie[y].next].bz;d[++j]=y; } } } int main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); scanf("%s",st+1); scanf("%d",&n); fo(i,1,n) { scanf("%s",s+1);int l=strlen(s+1),x=0; fo(j,1,l) { int y=s[j]-'0'; if (!trie[x].son[y]) trie[x].son[y]=++tot; x=trie[x].son[y]; } trie[x].bz=1; } makefail(); int l=strlen(st+1); f[0][0][1][1]=1; fo(i,0,l-1) fo(j,0,tot) fo(up,0,1) fo(zero,0,1) if (f[i][j][up][zero]) { fo(k,0,9) { int x=j; if (!k&&zero) continue; if (up&&k>st[i+1]-'0') continue; while (x&&!trie[x].son[k]) x=trie[x].next; x=trie[x].son[k];int y=up&&k==st[i+1]-'0'; if (trie[x].bz) continue; f[i+1][x][y][0]=(f[i+1][x][y][0]+ f[i][j][up][zero])%mo; } if (zero) f[i+1][j][0][1]=(f[i+1][j][0][1]+ f[i][j][up][1]); } fo(i,0,tot) fo(j,0,1) ans=(ans+f[l][i][j][0])%mo; printf("%lld",ans); }
相关文章推荐
- poj 3259 Wormholes 最短路(Bellman_Ford)
- C#中的代码书写规范以及命名规范
- http协议详解之url篇
- ANR Warning,RemoteViews can only be used once ,if not 问题
- 几个性能测试工具
- c++学习之同名隐藏
- 大牛们的博客
- Bellman-Ford算法模板
- shell脚本学习笔记 (流编辑器sed)
- 素数环
- 南阳题目364-田忌赛马
- 几个性能测试工具
- C#读取Excel数据到数组
- c++中的日期和时间
- 匈牙利命名法
- POJ 2688 Cleaning Robot(状压dp+bfs)
- 基于 SoapUI 工具测试 Rest 服务
- 【ANDROID游戏开发二十四】360°平滑游戏摇杆(触屏方向导航)
- poj1061 poj2115 扩展欧几里德算法
- 在Android Studio中导入github上的项目