bzoj 3530 [Sdoi2014]数数

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3530 [Sdoi2014]数数相关的知识,希望对你有一定的参考价值。

传送门

de了整整三个小时bug.

一直担心我的数位dp,然而并没错。

AC自动机各种毛病,fail怎么都不对,DE到怀疑人生,

最后发现我tmd用了一个栈来get_fail;

一直用stl突然心血来潮要手写一个队列,结果我tmd写成了一个栈。。

今晚真的是怀疑人生,

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=1507; 
const int mod=1e9+7;
typedef long long LL;
using namespace std;
int m,lim[N],s[N];
LL dp[N][N][3],ans;

void read(int a[]) {
    char ch=getchar(); 
    while(ch<0||ch>9) ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) a[++a[0]]=ch-0;
}

int rt,tot,ch[N][10],is[N],fail[N];
void insert() {
    int x=rt;
    for(int i=1;i<=s[0];i++) {
        int c=s[i];
        if(!ch[x][c]) ch[x][c]=++tot;
        x=ch[x][c];
    }
    is[x]=1;
}

queue<int>que;
void get_fail() {
    que.push(rt);
    while(!que.empty()) {
        int x=que.front();
        que.pop();
        for(int i=0;i<10;i++) if(ch[x][i]) {
            int y=ch[x][i];
            if(x==rt) fail[y]=rt;
            else {
                int z=fail[x];
                for(;!ch[z][i]&&z;z=fail[z]);
                if(ch[z][i]) fail[y]=ch[z][i];
                else fail[y]=rt;
                if(is[fail[y]]) is[y]=1;
            }
            que.push(ch[x][i]);
        }
    }
}

void pls(LL &a,LL b) { a+=b; if(a>=mod) a-=mod;}

void solve() {
    dp[0][0][1]=1;
    dp[0][0][2]=1;
    for(int i=1;i<=lim[0];i++) 
        for(int j=0;j<=tot;j++) if(!is[j]&&(dp[i-1][j][0]||dp[i-1][j][1]||dp[i-1][j][2])) {
            for(int k=(i==1);k<10;k++) {
                int y=ch[j][k];
                if(!y) {
                    int tp=fail[j];
                    while(!ch[tp][k]&&tp) tp=fail[tp];
                    if(ch[tp][k]) y=ch[tp][k]; else y=rt;
                }
                if(is[y]) continue;
                if(i==3&&y==0) {
                    int cnm=0;
                }
                pls(dp[i][y][2],dp[i-1][j][2]);
                pls(dp[i][y][0],dp[i-1][j][0]);
                if(k<lim[i]) pls(dp[i][y][0],dp[i-1][j][1]);
                if(k==lim[i]) pls(dp[i][y][1],dp[i-1][j][1]);
            }
        }
    for(int i=1;i<=lim[0];i++) {
        int debug=1;
        for(int j=0;j<=tot;j++) if(!is[j]) {
            if(i<lim[0]) pls(ans,dp[i][j][2]);
            else {
                pls(ans,dp[i][j][0]);
                pls(ans,dp[i][j][1]);
            }
        }
    }
}

int main() {
    read(lim);
    cin>>m;
    for(int i=1;i<=m;i++) {
        s[0]=0; read(s);
        insert();
    }
    get_fail();
    solve();
    printf("%lld\n",ans);
    return 0;
}
/*
7391
3
21
1923
98
*/ 
View Code

 

以上是关于bzoj 3530 [Sdoi2014]数数的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3530: [Sdoi2014]数数

BZOJ 3530 [Sdoi2014]数数

Bzoj3530: [Sdoi2014]数数

bzoj3530 [SDOI2014]数数

bzoj3530[Sdoi2014]数数 AC自动机+数位dp

BZOJ.3530.[SDOI2014]数数(AC自动机 数位DP)