zoukankan      html  css  js  c++  java
  • BZOJ3530 SDOI2014 数数

    传送门

    题目大意

    给定一个长度为$l$的数$n(lleq 1200)$,给定$m$个可能包含前导$0$的数字串$mleq 100$,求有多少个不超过$n$的的数在去前导零后不包含任何一个子串数字串。

    题解

    很裸的$AC$自动机$+$数位$Dp$题。

    对于$m$个数字串建$AC$自动机,$ F_{i,j,k={0,1}}$表示前$i$位匹配到$AC$自动机上的第$j$个节点,有$(k=1)$无$(k=0)$卡到数的上界的方案数,遇到结尾数字串的时候不进行转移即可。关于$n$前导$0$不能对匹配产生影响的问题,我们不能使用传统的令第最高$+1$位卡上界的初始状态答案为$1$,而是要枚举$n$的最高位在哪一位,枚举最高为是几,把这些位在$AC$自动机上的初始状态的$DP$值设为$1$,然后照常做即可。

    然后就是写$AC$自动机的时候一定要把$x$的标记从$fail_x$处转移过来,不然会出事情,比如$BZOJ$讨论群中的

    1234
    2
    121
    2

    正确代码输出:890
    错误代码输出:930

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 1510
    #define mod 1000000007
    using namespace std;
    int read(){
        int nm=0,fh=1; char cw=getchar();
        for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
        for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
        return nm*fh;
    }
    int n,m,fd[M],t[M][10],q[M<<1],hd,tl,rt,cnt,F[M][M][2],ans;
    void upd(int &x,int y){x=((x+y>=mod)?x+y-mod:x+y);}
    char ch[M],s[M]; bool vis[M];
    void ins(int &x,char *k,int rem){
        if(!x) x=++cnt; if(!rem){vis[x]=true;return;}
        ins(t[x][*k-'0'],k+1,rem-1);
    }
    int main(){
        scanf("%s",ch+1),n=strlen(ch+1);
        for(int T=read();T;--T) scanf("%s",s),ins(rt,s,strlen(s));
        for(int i=0;i<10;i++) if(t[rt][i]) fd[t[rt][i]]=1,q[tl++]=t[rt][i]; else t[rt][i]=1;
        for(fd[rt]=rt;hd<tl;){
            int x=q[hd++]; vis[x]|=vis[fd[x]];
            for(int k=0;k<10;k++){
                if(!t[x][k]) t[x][k]=t[fd[x]][k];
                else fd[t[x][k]]=t[fd[x]][k],q[tl++]=t[x][k];
            }
        }
        for(int i=1;i<=ch[1]-'0';i++) if(!vis[t[rt][i]]) F[1][t[rt][i]][i==(ch[1]-'0')]++;
        for(int i=2;i<=n;i++) for(int j=1;j<10;j++) if(!vis[t[rt][j]]) F[i][t[rt][j]][0]++;
        for(int i=1;i<=n;i++){
            for(int k=1;k<=cnt;k++){
                if(vis[k]){F[i][k][0]=F[i][k][1]=0;continue;}
                if(i==n){upd(ans,F[i][k][0]),upd(ans,F[i][k][1]);continue;}
                if(F[i][k][0]) for(int D=0;D<10;D++) upd(F[i+1][t[k][D]][0],F[i][k][0]);
                if(F[i][k][1]) for(int D=0;D<=ch[i+1]-'0';D++) upd(F[i+1][t[k][D]][D+'0'==ch[i+1]],F[i][k][1]);
            }
        } printf("%d
    ",ans); return 0;
    }
  • 相关阅读:
    web框架基础
    前端基础之DOM和jQuery
    前端基础之JavaScript
    前端基础之CSS
    福州大学W班-助教总结
    福州大学W班-个人最终成绩统计
    福州大学W班-Beta冲刺评分
    福州大学W班-alpha冲刺评分
    福州大学W班-团队作业-随堂小测(同学录)成绩
    福州大学W班-需求分析评分排名
  • 原文地址:https://www.cnblogs.com/OYJason/p/9837724.html
Copyright © 2011-2022 走看看