[bzoj3530][SDOI2014]数数
来源:互联网 发布:影视大全源码安装 编辑:程序博客网 时间:2024/05/21 03:19
题目描述
求不大于N的所有正整数中有多少个满足以下条件的数:给定字符串集合S,把该数当作字符串(没有前导0),集合S中没有任意一个字符串是该字符串的子集。
N的长度不超过1200,集合中所有字符串长度和不超过1500。
AC自动机上的DP
将集合内所有字符串建出一颗AC自动机。
那么,我们需要预处理一个这样的next[i,j]表示在结点i上接下要走j的话会调整到的结点是什么。(即预处理所有可能出现的调整结果)。
接下来就是数位DP了,设f[i,j,0]表示在第i位在AC自动机的结点j,当前比前i位比N小,那么f[i,j,1]就是与N相同,转移显然。
跳过所有状态满足当前结点可以匹配到一个单词(即S内的一个字符串),这样的结点j满足bz[j]=1(它是单词结点)或last[j]>0(它可以通过fail指针调整而匹配成功)。
参考程序
#include<cstdio>#include<algorithm>#include<cstring>#include<deque>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const ll mo=1000000007;struct dong{ ll x,y;};deque<dong> dl;ll next[1500+10][15],g[1500+10][15],fail[1500+10],last[1500+10];bool bz[1500+10];ll f[1200+10][1500+10][2];ll i,j,k,l,t,n,m,top,tot,ans;char s[1500+10],h[1500+10],ch;dong zlt;void insert(ll x,ll y){ if (y>top){ bz[x]=1; return; } if (g[x][h[y]-'0']==-1){ g[x][h[y]-'0']=++tot; ll i; fo(i,0,9) g[tot][i]=-1; } insert(g[x][h[y]-'0'],y+1);}void bfs(){ fo(i,0,9) if (g[0][i]!=-1){ zlt.x=g[0][i];zlt.y=0; dl.push_back(zlt); } while (!dl.empty()){ zlt=dl.front(); dl.pop_front(); k=zlt.x;l=zlt.y; fail[k]=l; if (bz[l]) last[k]=l;else last[k]=last[l]; fo(i,0,9){ if (g[k][i]==-1) continue; j=l; while (j&&g[j][i]==-1) j=fail[j]; if (g[j][i]!=-1) j=g[j][i]; zlt.x=g[k][i];zlt.y=j; dl.push_back(zlt); } }}void getnext(){ fo(i,0,tot){ fo(k,0,9){ j=i; while (j&&g[j][k]==-1) j=fail[j]; if (g[j][k]!=-1) j=g[j][k]; next[i][k]=j; } }}int main(){ //freopen("count.in","r",stdin);freopen("count.out","w",stdout); do{ ch=getchar(); if (ch=='\n') break; s[++n]=ch; }while (1); scanf("%lld",&m); ch=getchar(); fo(i,0,9) g[0][i]=-1; fo(i,1,m){ top=0; do{ ch=getchar(); if (ch=='\n') break; h[++top]=ch; }while (1); insert(0,1); } bfs(); getnext(); fo(i,1,s[1]-'0'-1) f[1][next[0][i]][0]=(f[1][next[0][i]][0]+1)%mo; f[1][next[0][s[1]-'0']][1]=(f[1][next[0][s[1]-'0']][1]+1)%mo; fo(i,1,n-1){ fo(j,1,9) f[i+1][next[0][j]][0]=(f[i+1][next[0][j]][0]+1)%mo; fo(j,0,tot){ if (bz[j]||last[j]) 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; } } } ans=0; fo(i,0,tot) if (!bz[i]&&!last[i]) ans=(ans+f[n][i][0]+f[n][i][1])%mo; printf("%lld\n",ans);}
0 0
- [bzoj3530][SDOI2014]数数
- bzoj3530【SDOI2014】数数
- bzoj3530: [Sdoi2014]数数
- BZOJ3530 [SDOI2014]数数
- [BZOJ3530] [Sdoi2014]数数 && AC自动机+dp
- 【bzoj3530】【sdoi2014】【数数】【AC自动机+数位dp】
- [BZOJ3530]-[Sdoi2014]数数-AC自动机+数位DP
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位dp)
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位DP)
- bzoj3530 [Sdoi2014]数数(AC自动机+数位DP)
- [SDOI2014]数数
- 【SDOI2014】数数
- 【SDOI2014】数数
- 【BZOJ 3530】 [Sdoi2014]数数
- [SDOI2014][JZOJ3624]数数
- BZOJ 3530 【Sdoi2014】 数数
- 3530: [Sdoi2014]数数
- bzoj 3530 [Sdoi2014]数数
- 学生管理系统(c版)
- MySql状态查看方法 MySql如何查看连接数和状态?
- get by name
- 【游】RTS的要素
- 第十三周 Prim算法的验证
- [bzoj3530][SDOI2014]数数
- 《Non-Negative Matrix Factorization for Polyphonic Music Transcription》译文
- spring 发送邮件
- oracle12c之jdbc连接可拔插数据库pdb的问题
- jdbc中如何处理Oracle BLOB字段
- 《Monkey Android》第12课ImageView
- 寄存器模块的使用-system generator
- 数组取出使用某一个entiti
- MySQL内存及虚拟内存优化设置