• bzoj 3530[Sdoi2014]数数


    3530: [Sdoi2014]数数

    Time Limit: 10 Sec  Memory Limit: 512 MB

    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 来解决

    因为对于位数比N少的,有前导零不好处理,所以我们分开讨论

    如果位数比N少,就和N的大小没有关系,我们可以直接转移

    g[i][j] 表示 当前是第 i 位 并且 走到 AC自动机上的 j 节点的方案数

    转移方程就是  g[i + 1][nxt[j]] += g[i][j] (!judge[nxt[j]]);

    ANS = sum(g[i][j]) (i = 1 ~ N - 1, j = 0 ~ tot);

    对于 位数和N相同的类似操作, 只需要加一维 表示前缀是否和N相同  0 表示不同, 1 表示相同

    如果是 0 的话后面就随便加, 1 再判断一下 , 和数位dp 思想很像

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <queue> 
      5 #include <algorithm>
      6 #define LL long long
      7 
      8 using namespace std; 
      9  
     10 queue<int> q;
     11 
     12 LL ans = 0;
     13 
     14 int N, M;
     15 int ln;
     16 char s[2000]; 
     17 LL g[1300][1600];
     18 LL f[2][1300][1600]; // 1 有限制, 0 表示无限制 
     19 int tot = 0;
     20 LL mod = 1e9 + 7;
     21 
     22 inline LL read()
     23 {
     24     LL x = 0, w = 1; char ch = 0;
     25     while(ch < '0' || ch > '9') {
     26         if(ch == '-') {
     27             w = -1;
     28         }
     29         ch = getchar();
     30     }
     31     while(ch >= '0' && ch <= '9') {
     32         x = x * 10 + ch - '0';
     33         ch = getchar();
     34     }
     35     return x * w;
     36 }
     37 
     38 const int MAXN = 1e6 + 10;
     39 
     40 int d[MAXN];
     41 
     42 struct trie {
     43     int str[15];
     44     int fail;
     45     int num;
     46     int judge;
     47     void init()
     48     {
     49         memset(str, 0, sizeof str);
     50         fail = 0;
     51         judge = 0;
     52     }
     53 } t[MAXN];
     54 
     55 void insert(int root, int k)
     56 {
     57     for(int i = 1; i <= k; i++) {
     58         int nxt = s[i] - '0';
     59         if(t[root].str[nxt] == 0) {
     60             t[root].str[nxt] = ++tot;
     61             t[tot].init();
     62             t[tot].num = nxt; 
     63         }
     64         root = t[root].str[nxt];
     65     }
     66     t[root].judge = 1;
     67 }
     68 
     69 void getfail()
     70 {
     71     for(int i = 0; i <= 9; i++) {
     72         if(t[0].str[i]) {
     73             q.push(t[0].str[i]);
     74         }
     75     }
     76     while(!q.empty()) {
     77         int tt = q.front();
     78         q.pop();
     79         for(int j = 0; j <= 9; j++) {
     80             if(t[tt].str[j]) {
     81                 int f = t[tt].fail;
     82                 while(t[f].str[j] == 0) {
     83                     if(f == 0) {
     84                         break;
     85                     }
     86                     f = t[f].fail;
     87                 }
     88                 t[t[tt].str[j]].fail = t[f].str[j];
     89                 q.push(t[tt].str[j]);
     90             }
     91         }
     92     }
     93 }
     94 
     95 int main()
     96 {
     97     scanf("%s", s + 1);
     98     ln = strlen(s + 1);
     99     for(int i = 1; i <= ln; i++) {
    100         d[i] = s[i] - '0';
    101     }
    102     M = read();
    103     for(int i = 1; i <= M; i++) {
    104         scanf("%s", s + 1);
    105         int len = strlen(s + 1);
    106         insert(0, len);
    107     }
    108     getfail();
    109     g[0][0] = 1;
    110     for(int i = 0; i < ln; i++) {
    111         for(int j = 0; j <= tot; j++) {
    112             for(int k = 0; k <= 9; k++) {
    113                 if(i == 0 && k == 0) {
    114                     continue;
    115                 }
    116                 int nxt = t[j].str[k];
    117                 int cnt = j;
    118                 while(nxt == 0) {
    119                     if(cnt == 0) {
    120                         break;
    121                     }
    122                     cnt = t[cnt].fail;
    123                     nxt = t[cnt].str[k];
    124                 }
    125                 if(!t[nxt].judge) {
    126                     g[i + 1][nxt] = (g[i + 1][nxt] + g[i][j]) % mod;
    127                 }
    128             }
    129         }
    130     }
    131     f[1][0][0] = 1;
    132     for(int i = 0; i < ln; i++) {
    133         for(int j = 0; j <= tot; j++) {
    134             for(int k = 0; k <= 9; k++) {
    135                 if(i == 0 && k == 0) {
    136                     continue;
    137                 }
    138                 int nxt = t[j].str[k];
    139                 int cnt = j;
    140                 while(nxt == 0) {
    141                     if(cnt == 0) {
    142                         break;
    143                     }
    144                     cnt = t[cnt].fail;
    145                     nxt = t[cnt].str[k];
    146                 }
    147                 if(!t[nxt].judge) {
    148                     if(k < d[i + 1]) {
    149                         f[0][i + 1][nxt] = (f[0][i + 1][nxt] + f[1][i][j] + f[0][i][j]) % mod;
    150                     } else if(k == d[i + 1]) {
    151                         f[0][i + 1][nxt] = (f[0][i + 1][nxt] + f[0][i][j]) % mod;
    152                         f[1][i + 1][nxt] = (f[1][i + 1][nxt] + f[1][i][j]) % mod;
    153                     } else {
    154                         f[0][i + 1][nxt] = (f[0][i + 1][nxt] + f[0][i][j]) % mod;
    155                     }
    156                 }
    157             }
    158         }
    159     }
    160     for(int i = 1; i < ln; i++) {
    161         for(int j = 0; j <= tot; j++) {
    162             ans = (ans + g[i][j]) % mod; 
    163         }
    164     }
    165     /*for(int i = 1; i <= ln; i++) {
    166         for(int j = 0; j <= tot; j++) {
    167             cout<<t[j].num<<" "<<f[0][i][j]<<" "<<f[1][i][j]<<endl;
    168         }
    169         cout<<endl<<endl;
    170     }*/
    171     for(int j = 0; j <= tot; j++) {
    172         ans = (ans + f[0][ln][j] + f[1][ln][j]) % mod;
    173     }
    174     printf("%lld
    ", ans);
    175 }
    176 
    177 
    178 
    179 /*
    180 
    181 20
    182 3
    183 2
    184 3
    185 14
    186 
    187 */
    View Code
  • 相关阅读:
    ef左联三张表案例
    sql常用语句汇总
    最初的ajax案例
    asp.net mvc请求响应模型原理回顾
    viewstate cookie和session原理回顾
    一般处理程序装配数据到html页的原理
    asp.net页面生命周期回顾
    rocketMQ 消息的 tag
    rocketMQ 订阅关系
    rocketMQ retry 消息的实现
  • 原文地址:https://www.cnblogs.com/wuenze/p/8581988.html
Copyright © 2020-2023  润新知