• bzoj 3530 : [Sdoi2014]数数


      一眼AC自动机上DP,f[i][j][0]到第j个节点表示前i位与n一样的方案,1表示不一样的方案。

      事实证明我每回写数位dp都要wa到神志模糊,数据一有0就跪,所以加了各种特判。。。

      因为如果数据中有0032这种的话直接dp会把32判为不合法,而事实上它是合法的,因为要去掉前缀0.

      所以每回从根向0的边转移时要少转移1,相当于把0000....这个全为0的前缀保留在根,为了保留这个前缀还要从第二次开始每次f[i][0][1]++。

      好像每次写数位dp都是加了一堆特判才过的。。。

      

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #include<algorithm>
      6 #define p 1000000007
      7 using namespace std;
      8 int m,n;
      9 char s[2000];
     10 int ch[2000][10];int cnt;
     11 bool v[2000];
     12 bool flag;
     13 void build()
     14 {
     15     int len=strlen(s);
     16     int now=0;
     17     for(int i=0;i<len;i++)
     18     {
     19         int c=s[i]-'0';
     20         if(ch[now][c])now=ch[now][c];
     21         else
     22         {
     23             ch[now][c]=++cnt;
     24             now=ch[now][c];
     25         }
     26     }
     27     v[now]=1;
     28 }
     29 queue<int>q;
     30 int f[2000];
     31 int ans;
     32 void AC()
     33 {
     34     for(int i=0;i<10;i++)
     35     {
     36         if(ch[0][i])q.push(ch[0][i]);
     37     }
     38     while(!q.empty())
     39     {
     40         int tmp=q.front();q.pop();
     41         for(int i=0;i<10;i++)
     42         {
     43             if(ch[tmp][i])
     44             {
     45                 f[ch[tmp][i]]=ch[f[tmp]][i];
     46                 q.push(ch[tmp][i]); 
     47                 if(v[f[ch[tmp][i]]])v[ch[tmp][i]]=1;
     48             }
     49             else
     50             {
     51                 ch[tmp][i]=ch[f[tmp]][i];
     52             }
     53         }
     54     }
     55 }
     56 int now[2000][2],pre[2000][2];
     57 char a[2000];
     58 int be[2000];
     59 int main()
     60 {
     61     scanf("%s",a);
     62     n=strlen(a);
     63     scanf("%d",&m);
     64     for(int i=1;i<=m;i++)
     65     {
     66         scanf("%s",s);
     67         build();
     68     }
     69     AC();
     70     pre[0][0]=1;
     71     for(int i=0;i<n;i++)
     72     {
     73         int x=a[i]-'0';
     74         if(i)pre[0][1]++;
     75         for(int j=0;j<=cnt;j++)
     76         {
     77             if(v[j])continue;
     78             for(int k=0;k<x;k++)
     79             {
     80                 if(!i&&!k)continue;
     81                 now[ch[j][k]][1]+=pre[j][0];
     82                 now[ch[j][k]][1]%=p;
     83             }
     84             now[ch[j][x]][0]+=pre[j][0];
     85             now[ch[j][x]][0]%=p;
     86             for(int k=0;k<10;k++)
     87             {
     88                 now[ch[j][k]][1]+=pre[j][1]-(!j&&k==0&&i!=0);
     89                 now[ch[j][k]][1]%=p;
     90             }
     91         }
     92         for(int j=0;j<=cnt;j++)
     93         {
     94             if(v[j])continue;
     95             if(i==n-1)
     96             {
     97                 ans+=now[j][1];
     98                 if(ans>=p)ans-=p;
     99                 ans+=now[j][0];
    100                 if(ans>=p)ans-=p;
    101             }
    102             pre[j][0]=now[j][0];
    103             pre[j][1]=now[j][1];
    104             now[j][0]=now[j][1]=0;
    105         }
    106     }
    107     printf("%d
    ",ans);
    108     return 0;
    109 }
  • 相关阅读:
    asp.net AD 域验证
    ASP.NET身份验证
    .Net默认IE版本号的两种方式
    (转)移动端自适应方案
    (转)手机web——自适应网页设计(html/css控制)
    (转)优雅降级和渐进增强的区别
    (转)hasLayout与BFC的触发条件
    (转)js中几种实用的跨域方法原理详解
    (转)js实现继承的5种方式
    (转)js 判断各种数据类型
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6435963.html
Copyright © 2020-2023  润新知