Bzoj 3530 數數

[1,n](n101000) 中不包含給定數字作爲字串的數字個數(mod109+7) ,給定數字總長度1500


一眼看過去是一個用AC自動機表示狀態,用數位dp的模板題

注意前導零是不會被統計到的

具體見代碼

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1600,maxLen = 10;
const int mod = 1e9+7;

#define LL long long 

queue<int> Q;
int toid(char c){ return c - '0'; }

struct acam{
    int nex[maxn][maxLen],fail[maxn];
    int cnt[maxn];
    int _cnt,root;
    int newNode(){
        memset(nex[_cnt],fail[_cnt] = -1,sizeof(nex[_cnt]));
        cnt[_cnt] = 0;
        return _cnt++;
    }
    void init(){
        _cnt = 0;
        root = newNode();
    }
    void insert(char *arr){
        int st = root;
        for(int i=0;arr[i];i++){
            int & stx = nex[st][toid(arr[i])]; 
            if(stx == -1) stx = newNode();
            st = stx;
        }
        cnt[st]++;
    }
    void build(){
        while(Q.empty()==false) Q.pop();
        fail[root] = root;
        int st;
        for(int i=0;i<maxLen;i++){
            if((st = nex[root][i]) != -1){
                fail[st] = root;
                Q.push(st);
            }
            else nex[root][i] = root;
        }
        while(Q.empty()==false){
            st = Q.front(),Q.pop();
            for(int i=0;i<maxLen;i++){
                if(nex[st][i] != -1){
                    int fst = fail[st],son = nex[st][i];
                    while(fst != root && nex[fst][i] == -1)
                        fst = fail[fst];
                    fail[son] = nex[fst][i] == -1 ? root : nex[fst][i]; 
                    Q.push(son);
                }
                else{
                    nex[st][i] = nex[fail[st]][i];
                }
            }
        }
    }
}acam;

int num[maxn];
LL dp[maxn][2][maxn][2];

LL dfs(int pos,bool bnd,int st,int az){
    if(pos < 0) return 1;
    LL & ndp = dp[pos][bnd][st][az];
    if(~ndp) return ndp;
    ndp = 0;
    int bound = bnd ? num[pos] : 9;
    for(int i=0;i<=bound;i++){
        if(az && i == 0){
            (ndp += dfs(pos-1,bnd && i == bound,st,az && i == 0))%= mod;
        }
        else{
            int nex = acam.nex[st][i];
            if(acam.cnt[nex] == 0)
                (ndp += dfs(pos-1,bnd && i == bound,nex,az && i == 0)) %= mod;
        }
    }
    return ndp;
}

char arr[2000];
int main(){
    scanf("%s",arr);
    int len = strlen(arr);
    reverse(arr,arr+len);
    for(int i=0;i<len;i++) num[i] = toid(arr[i]);
    int m;
    scanf("%d",&m);
    acam.init();
    while(m--){
        scanf("%s",arr);
        acam.insert(arr);
    }
    acam.build();
    memset(dp,-1,sizeof(dp));
    printf("%lld\n",(dfs(len-1,true,0,true)-1+mod) % mod);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章