zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    convert image to base64 and post to RESTful wcf
    在android webview实现截屏的手动tounchmove裁剪图片
    How to use jquery ajax and android request security RESTful WCF
    using swfUpload in asp.net mvc
    using HttpClient and sending json data to RESTful server in adroind
    ODP.NET数据访问
    android image watermark
    解决国内不能访问github的问题
    idapro权威指南第二版阅读笔记第九章 交叉引用和绘图功能
    idapro权威指南第二版阅读笔记第二章 逆向和反汇编工具
  • 原文地址:https://www.cnblogs.com/wuenze/p/8581988.html
Copyright © 2011-2022 走看看