Description
我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。
Input
输入的第一行包含整数N。
接下来一行一个整数M,表示S中元素的数量。
接下来M行,每行一个数字串,表示S中的一个元素。
Output
输出一行一个整数,表示答案模109+7的值。
Sample Input
20
3
2
3
14
Sample Output
14
HINT
下表中l表示N的长度,L表示S中所有串长度之和。
1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500
题解
就先建一个AC自动机
然后做一下数位DP就好了
代码很丑,看看数组的表示就好了
要注意的是,2和02不是一个东西
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int MOD=1e9+7;
const int N=1505;
struct node{
int son[10],fail;
bool tf;//是不是终点
}s[N];int num=0;
char ss[N];
int m;
void init (int x)
{
//printf("%d\n",x);
s[x].tf=false;s[x].fail=0;
for (int u=0;u<10;u++) s[x].son[u]=-1;
}
void bt ()
{
int len=strlen(ss),now=0;
for (int u=0;u<len;u++)
{
int x=ss[u]-'0';
if (s[now].son[x]==-1)
{
s[now].son[x]=++num;
init(num);
}
now=s[now].son[x];
}
//printf("YES:%d\n",now);
s[now].tf=true;
}
queue<int> q;
void bfs ()
{
int x;q.push(0);
while (!q.empty())
{
int x=q.front();
for (int u=0;u<10;u++)
{
int son=s[x].son[u],f=s[x].fail;
if (son>=0)
{
if (x==0) s[son].fail=0;
else s[son].fail=s[f].son[u];
q.push(son);
}
else
{
if (x==0) s[x].son[u]=0;
else s[x].son[u]=s[f].son[u];
}
}
q.pop();
}
}
bool vis[N];
void dfs (int x)
{
if (vis[x]) return ;
vis[x]=true;
int Fail=s[x].fail;
dfs(Fail);
s[x].tf=(s[x].tf|s[Fail].tf);
}
char n[N];
int ooo;
int f[N][2][2][N];
int solve (int x,bool tf,bool tf1,int y)//当前到第几位了 是否已经小了 是否非0位 在AC自动机上是哪一位
{
if (tf1==false) y=0;
if (s[y].tf==true) return 0;
// printf("%d %d %d %d\n",x,tf,tf1,y);
if (x>ooo) return tf1==false?0:1;
if (f[x][tf][tf1][y]!=0) return f[x][tf][tf1][y];
if (tf==true)//可以随便填
{
f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,tf1,s[y].son[0]))%MOD;//填0
for (int u=1;u<=9;u++)
{
// printf("NO:%d %d %d %d\n",x,u,solve(x+1,true,true,s[y].son[u]),s[y].son[u]);
f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,true,s[y].son[u]))%MOD;
}
}
else
{
int now=n[x]-'0';
if (0!=now) f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,tf1,s[y].son[0]))%MOD;
for (int u=1;u<now;u++)
f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,true,s[y].son[u]))%MOD;
if (now==0) f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,false,tf1,s[y].son[now]))%MOD;
else f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,false,true,s[y].son[now]))%MOD;
}
// printf("YES:%d %d %d %d %d\n",x,tf,tf1,y,f[x][tf][tf1][y]);
return f[x][tf][tf1][y];
}
int main()
{
memset(f,0,sizeof(f));
scanf("%s",n+1); ooo=strlen(n+1);
scanf("%d",&m);
init(0);
for (int u=1;u<=m;u++)
{
scanf("%s",ss);
bt();
}
bfs();
memset(vis,false,sizeof(vis));vis[0]=true;
for (int u=1;u<=num;u++)
{
//if (s[u].tf) printf("OZY:%d\n",u);
dfs(u);
}
printf("%d\n",(solve(1,false,false,0)+MOD)%MOD);
return 0;
}