【BZOJ3530】数数(SDOI2014)-AC自动机+数位DP
2018-04-03 22:50
513 查看
测试地址:数数
做法:本题需要用到AC自动机+数位DP。
首先看到多模式串匹配,自然想到用AC自动机来做。用AC自动机构造出状态转移图后,令f(i,j,k)f(i,j,k)为匹配了最高的ii位,匹配到AC自动机上的jj点,卡上界的情况为kk(k=0k=0表示不卡上界,接下来选的数不受限制,否则反之)的方案数,那么做一个数位DP即可。注意处理数字有前导00的情况。
感觉数位DP还是好难理解……还要多加学习……
以下是本人代码:
做法:本题需要用到AC自动机+数位DP。
首先看到多模式串匹配,自然想到用AC自动机来做。用AC自动机构造出状态转移图后,令f(i,j,k)f(i,j,k)为匹配了最高的ii位,匹配到AC自动机上的jj点,卡上界的情况为kk(k=0k=0表示不卡上界,接下来选的数不受限制,否则反之)的方案数,那么做一个数位DP即可。注意处理数字有前导00的情况。
感觉数位DP还是好难理解……还要多加学习……
以下是本人代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1000000007; int n,m,rt=0,tot=0,len,ch[2010][10]={0},fail[2010]; int h,t,q[2010],nxt[2010][10]; ll f[2][2010][2]={0}; char N[2010],s[2010]; bool forb[2010]={0}; void insert(int &v,int step) { if (!v) v=++tot; if (step>=len) {forb[v]=1;return;} insert(ch[v][s[step]-'0'],step+1); } void init() { scanf("%s",N); n=strlen(N); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",s); len=strlen(s); insert(rt,0); } } void build() { h=t=q[1]=1; while(h<=t) { int v=q[h++]; for(int i=0;i<=9;i++) if (ch[v][i]) { int x=fail[v]; while(x&&!ch[x][i]) x=fail[x]; if (!x) fail[ch[v][i]]=1; else fail[ch[v][i]]=ch[x][i]; forb[ch[v][i]]=forb[ch[v][i]]||forb[fail[ch[v][i]]]; q[++t]=ch[v][i]; } } } void work() { for(int i=1;i<=tot;i++) for(int j=0;j<=9;j++) { int x=i; while(x&&!ch[x][j]) x=fail[x]; if (!x) nxt[i][j]=1; else nxt[i][j]=ch[x][j]; } } void add(ll &a,ll b) { a=(a+b)%mod; } void dp() { int now=1,past=0; for(int i=0;i<n;i++) { memset(f[now],0,sizeof(f[now])); for(int j=1;j<=tot;j++) { for(int up=0;up<=1;up++) for(int k=0;k<=(up?(N[i]-'0'):9);k++) if (!forb[nxt[j][k]]) { if (up&&k==(N[i]-'0')) add(f[now][nxt[j][k]][1],f[past][j][up]); else add(f[now][nxt[j][k]][0],f[past][j][up]); } if (j==1) { for(int k=1;k<=(i?9:N[i]-'0');k++) if (!forb[nxt[j][k]]) { if (!i&&k==N[i]-'0') add(f[now][nxt[j][k]][1],1); else add(f[now][nxt[j][k]][0],1); } } } swap(now,past); } ll ans=0; for(int i=1;i<=tot;i++) if (!forb[i]) { add(ans,f[past][i][0]); add(ans,f[past][i][1]); } printf("%lld",ans); } int main() { init(); build(); work(); dp(); return 0; }
相关文章推荐
- 【BZOJ3530】[Sdoi2014]数数 AC自动机+数位DP
- BZOJ.3530.[SDOI2014]数数(AC自动机 数位DP)
- [bzoj3530][Sdoi2014]数数_AC自动机_数位dp
- [BZOJ3530][SDOI2014]数数 AC自动机+数位DP
- BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]
- [BZOJ3530]-[Sdoi2014]数数-AC自动机+数位DP
- bzoj3530 [Sdoi2014]数数(AC自动机+数位DP)
- 【bzoj3530】【sdoi2014】【数数】【AC自动机+数位dp】
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位dp)
- [ AC自动机 数位DP ] [ SDOI2014 ] BZOJ3530
- [BZOJ3530][Sdoi2014]数数(AC自动机上数位DP)
- [BZOJ3530][SDOI2014]数数(AC自动机+数位dp)
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位DP)
- bzoj 3530: [Sdoi2014]数数 数位dp
- bzoj 3530: [Sdoi2014]数数 (AC自动机+数位DP)
- [BZOJ]3530 [SDOI2014] 数数 AC自动机 + DP
- BZOJ 3530 数数【AC自动机+数位dp】
- bzoj 3530 [Sdoi2014]数数
- 【BZOJ 3530】【SDOI 2014】数数
- Bzoj3530 [Sdoi2014]数数