bzoj 3530 [Sdoi2014]数数
de了整整三个小时bug.
一直担心我的数位dp,然而并没错。
AC自动机各种毛病,fail怎么都不对,DE到怀疑人生,
最后发现我tmd用了一个栈来get_fail;
一直用stl突然心血来潮要手写一个队列,结果我tmd写成了一个栈。。
今晚真的是怀疑人生,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=1507;
const int mod=1e9+7;
typedef long long LL;
using namespace std;
int m,lim[N],s[N];
LL dp[N][N][3],ans;
void read(int a[]) {
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) a[++a[0]]=ch-'0';
}
int rt,tot,ch[N][10],is[N],fail[N];
void insert() {
int x=rt;
for(int i=1;i<=s[0];i++) {
int c=s[i];
if(!ch[x][c]) ch[x][c]=++tot;
x=ch[x][c];
}
is[x]=1;
}
queue<int>que;
void get_fail() {
que.push(rt);
while(!que.empty()) {
int x=que.front();
que.pop();
for(int i=0;i<10;i++) if(ch[x][i]) {
int y=ch[x][i];
if(x==rt) fail[y]=rt;
else {
int z=fail[x];
for(;!ch[z][i]&&z;z=fail[z]);
if(ch[z][i]) fail[y]=ch[z][i];
else fail[y]=rt;
if(is[fail[y]]) is[y]=1;
}
que.push(ch[x][i]);
}
}
}
void pls(LL &a,LL b) { a+=b; if(a>=mod) a-=mod;}
void solve() {
dp[0][0][1]=1;
dp[0][0][2]=1;
for(int i=1;i<=lim[0];i++)
for(int j=0;j<=tot;j++) if(!is[j]&&(dp[i-1][j][0]||dp[i-1][j][1]||dp[i-1][j][2])) {
for(int k=(i==1);k<10;k++) {
int y=ch[j][k];
if(!y) {
int tp=fail[j];
while(!ch[tp][k]&&tp) tp=fail[tp];
if(ch[tp][k]) y=ch[tp][k]; else y=rt;
}
if(is[y]) continue;
if(i==3&&y==0) {
int cnm=0;
}
pls(dp[i][y][2],dp[i-1][j][2]);
pls(dp[i][y][0],dp[i-1][j][0]);
if(k<lim[i]) pls(dp[i][y][0],dp[i-1][j][1]);
if(k==lim[i]) pls(dp[i][y][1],dp[i-1][j][1]);
}
}
for(int i=1;i<=lim[0];i++) {
int debug=1;
for(int j=0;j<=tot;j++) if(!is[j]) {
if(i<lim[0]) pls(ans,dp[i][j][2]);
else {
pls(ans,dp[i][j][0]);
pls(ans,dp[i][j][1]);
}
}
}
}
int main() {
read(lim);
cin>>m;
for(int i=1;i<=m;i++) {
s[0]=0; read(s);
insert();
}
get_fail();
solve();
printf("%lld\n",ans);
return 0;
}
/*
7391
3
21
1923
98
*/