• 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

    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 }
  • 相关阅读:
    1032. Sharing (25)
    1031. Hello World for U (20)
    1030. Travel Plan (30)
    1029. Median (25)
    1028. List Sorting (25)
    1026. Table Tennis (30)
    win10 tortoiseSVN文件夹及文件图标不显示解决方法
    qrcode.react和jquery.qrcode生成二维码
    js来获取所有屏幕适配的总结
    handsontable整理
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8350265.html
Copyright © 2020-2023  润新知