bzoj3530 [Sdoi2014]数数
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
3
2
3
14
Sample Output
14
HINT
下表中l表示N的长度,L表示S中所有串长度之和。
1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500
正解:$AC$自动机+数位$dp$。
很裸的题,直接在$AC$自动机上跑数位$dp$就行了。
细节:$AC$自动机建成$trie$图可以保证复杂度。
第一位不能为$0$,且只有位数为$n$时才会有限制。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define rhl (1000000007) 6 7 using namespace std; 8 9 int f[1505][1205][2],ch[1505][26],val[1505],fa[1505],q[1505],n,m,sz,len,ans; 10 char s[1505],cs[1505]; 11 12 il int gi(){ 13 RG int x=0,q=1; RG char ch=getchar(); 14 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 15 if (ch=='-') q=-1,ch=getchar(); 16 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 17 return q*x; 18 } 19 20 il void insert(char *s,RG int len){ 21 RG int x=0,c; 22 for (RG int i=1;i<=len;++i){ 23 c=s[i]-'0'; 24 if (!ch[x][c]) ch[x][c]=++sz; x=ch[x][c]; 25 } 26 val[x]=1; return; 27 } 28 29 il void build(){ 30 RG int h=0,t=0; 31 for (RG int c=0;c<10;++c) if (ch[0][c]) q[++t]=ch[0][c]; 32 while (h<t){ 33 RG int x=q[++h],v,j; 34 for (RG int c=0;c<10;++c){ 35 if (!ch[x][c]){ ch[x][c]=ch[fa[x]][c]; continue; } 36 v=ch[x][c],j=fa[x]; while (j && !ch[j][c]) j=fa[j]; 37 fa[v]=ch[j][c],q[++t]=v,val[v]|=val[fa[v]]; 38 } 39 } 40 return; 41 } 42 43 il int dfs(RG int x,RG int p,RG int l){ 44 if (p>n) return 1; 45 if (f[x][p][l]!=-1) return f[x][p][l]; 46 RG int res=0,lim=s[p]-'0'; 47 for (RG int c=0;c<10;++c){ 48 if (l && c>lim) break; 49 if (val[ch[x][c]]) continue; 50 res+=dfs(ch[x][c],p+1,l&&c==lim); 51 if (res>=rhl) res-=rhl; 52 } 53 return f[x][p][l]=res; 54 } 55 56 int main(){ 57 #ifndef ONLINE_JUDGE 58 freopen("number.in","r",stdin); 59 freopen("number.out","w",stdout); 60 #endif 61 scanf("%s",s+1),n=strlen(s+1),m=gi(); 62 for (RG int i=1;i<=m;++i) 63 scanf("%s",cs+1),len=strlen(cs+1),insert(cs,len); 64 build(),memset(f,-1,sizeof(f)); 65 for (RG int i=1;i<=n;++i) 66 for (RG int j=1;j<10;++j){ 67 if (i==1 && j>s[i]-'0') break; 68 if (val[ch[0][j]]) continue; 69 ans+=dfs(ch[0][j],i+1,i==1&&j==s[i]-'0'); 70 if (ans>=rhl) ans-=rhl; 71 } 72 cout<<ans; return 0; 73 }