zoukankan      html  css  js  c++  java
  • bzoj [Sdoi2014]数数 AC自动机上dp

    [Sdoi2014]数数

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 1264  Solved: 636
    [Submit][Status][Discuss]

    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

    Source

    Round 1 day 1

    AC自动机建好后f[i][j][k]表示i这个点j长度k=0表示小于,1表示等于

    这样转移很好转移 IL的复杂度随便跑,

    虑到不能有前导零,所以填每一位的时候可以把根节点单独转移一次1~9

      1 #pragma GCC optimzie(2)
      2 #pragma G++ optimize(2)
      3 #include<cstring>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<cstdio>
      7 #include<algorithm>
      8 #include<queue>
      9 
     10 #define ll long long
     11 #define N 2007
     12 #define mod 1000000007
     13 using namespace std;
     14 inline int read()
     15 {
     16     int x=0,f=1;char ch=getchar();
     17     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     18     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     19     return x*f;
     20 }
     21 
     22 int m,len,l;
     23 ll ans;
     24 struct Node
     25 {
     26     int c[11],suf;
     27     bool flag;
     28 }trie[N];
     29 int cnt=1,rt=1;
     30 ll f[1207][1507][2];
     31 char ch[N],n[N];
     32 
     33 void insert()
     34 {
     35     int now=rt;
     36     for (int i=1;i<=len;i++)
     37         if(trie[now].c[ch[i]-'0'])now=trie[now].c[ch[i]-'0'];
     38         else
     39         {
     40             trie[now].c[ch[i]-'0']=++cnt;
     41             now=cnt;
     42         }
     43     trie[now].flag=true;
     44 }
     45 void make_AC()
     46 {
     47     for (int i=0;i<10;i++)
     48         trie[0].c[i]=1;
     49     queue<int>q;q.push(1);
     50     trie[1].suf=0;
     51     while(!q.empty())
     52     {
     53         int u=q.front();q.pop();
     54         for (int i=0;i<10;i++)
     55             if(trie[u].c[i])
     56             {
     57                 trie[trie[u].c[i]].suf=trie[trie[u].suf].c[i];
     58                 if(trie[trie[trie[u].c[i]].suf].flag)trie[trie[u].c[i]].flag=true;
     59                 q.push(trie[u].c[i]);
     60             }
     61             else trie[u].c[i]=trie[trie[u].suf].c[i];
     62     }
     63 }
     64 void solve()
     65 {
     66     /*f[0][1][1]=1;
     67     for (int i=0;i<l;i++)
     68         for (int j=1;j<=cnt;j++)
     69         {
     70             if (f[i][j][1]&&!trie[j].flag)
     71             {
     72                 for (int k=0;k<10;k++)
     73                     if (n[i+1]-'0'>k)(f[i+1][trie[j].c[k]][0]+=f[i][j][1])%=mod;
     74                     else if(n[i+1]-'0'==k)(f[i+1][trie[j].c[k]][1]+=f[i][j][1])%=mod;
     75             }
     76             if(f[i][j][0]&&!trie[j].flag)
     77             {
     78                 for (int k=0;k<10;k++)
     79                     (f[i+1][trie[j].c[k]][0]+=f[i][j][0])%=mod;
     80             }
     81         }*/
     82     for (int i=1;i<=l;i++)
     83     {
     84         for (int z=1,v=trie[1].c[z];z<=9;v=trie[1].c[++z])
     85         {
     86             if(i!=1||z<n[i]-'0')(f[i][v][0]+=1)%=mod;
     87             else if(z==n[i]-'0')(f[i][v][1]+=1)%=mod;
     88         }
     89         for (int j=1;j<=cnt;j++)
     90             if(!trie[j].flag)
     91                 for (int c=0,v=trie[j].c[c];c<=9;v=trie[j].c[++c])
     92                 {
     93                     (f[i][v][0]+=f[i-1][j][0])%=mod;
     94                     if(c<n[i]-'0')(f[i][v][0]+=f[i-1][j][1])%=mod;
     95                     else if(c==n[i]-'0')(f[i][v][1]+=f[i-1][j][1])%=mod;
     96                 }
     97     }
     98         
     99     for (int i=1;i<=cnt;i++)
    100         if(!trie[i].flag)(ans+=f[l][i][0]+f[l][i][1])%=mod;
    101     printf("%lld",ans);
    102 }
    103 int main()
    104 {
    105     scanf("%s",n+1);l=strlen(n+1);
    106     m=read();
    107     for (int i=1;i<=m;i++)
    108     {
    109         scanf("%s",ch+1),len=strlen(ch+1);
    110         insert();
    111     }
    112     make_AC(),solve();
    113 }
  • 相关阅读:
    【转】size_t和ssize_t
    WCF订票系统DEMO
    VS2008显示解决方案的方法
    一些好用的开源控件
    SQL 的Over 子句
    Sql2005高效分页语句
    使用winform的showdialog小心内存泄漏
    字符串连接类(Javascript)
    SharpZipLib 的使用
    浅谈持久化
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8530904.html
Copyright © 2011-2022 走看看