CF 434C Tachibana Kanade's Tofu[数位dp+AC自动机]

 

  • Solution

//本代码压掉后两维 
#include<cstdio>
#define max(a,b) (a<b?b:a)
using namespace std;
inline void read(int &x){
    register char ch=getchar();x=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
const int N=205,M=505;
const int mod=1e9+7;
int n,m,K,cnt=1,a[N],b[N];int bfs[N];
int v[N],fail[N],next[N][20],trans[N][20];
int f[N][N][M];
inline void insert(int l){
    int x,now=1;
    for(int i=1;i<=l;i++){
        read(x);
        if(!next[now][x]) next[now][x]=++cnt;
        now=next[now][x];
    }
    read(x);v[now]+=x;
}
inline void build_AC(){
    int l=0,r=0,x,y;
    for(int i=0;i<m;i++){
        if(next[1][i]){
            x=next[1][i];
            fail[x]=1;
            trans[1][i]=x;
            bfs[++r]=x;
        }
        else{
            trans[1][i]=1;
        }
    }
    while(l!=r){
        x=bfs[++l];
        v[x]+=v[fail[x]];
        for(int i=0,p;i<m;i++){
            if(next[x][i]){
                y=next[x][i];
                for(p=fail[x];p&&!next[p][i];p=fail[p]);
                if(p) fail[y]=next[p][i];
                else fail[y]=1;
                trans[x][i]=y;
                bfs[++r]=y;
            }
            else{
                for(p=fail[x];p&&!next[p][i];p=fail[p]);
                if(p) trans[x][i]=next[p][i];
                else trans[x][i]=1;
            }
        }
    }
}
inline void Plus(int &x,int y){
    x+=y;
    if(x>=mod) x-=mod;
}
inline void prep(int bit){//无任何限制预处理 
    for(int i=1;i<=cnt;i++) f[0][i][0]=1;
    for(int i=1;i<=bit;i++){
        for(int j=1;j<=cnt;j++){
            for(int p=0,x;p<m;p++){
                x=trans[j][p];
                for(int k=v[x];k<=K;k++){
                    Plus(f[i][j][k],f[i-1][x][k-v[x]]);
                }
            }
        }
    }
}
inline int work(int *a,bool flag){
    int x,y,w,ans=0;
    //取出最高位后,保证无前导零后,无限制 
    for(int i=1;i<a[0];i++){
        for(int j=1;j<m;j++){
            y=trans[1][j];
            w=v[y];
            for(int k=w;k<=K;k++){
                Plus(ans,f[i-1][y][k-w]);
            }
        }
    }
    //走一遍上界,要保证无前导零 
    x=1;w=0;
    for(int i=1;i<=a[0];i++){
        for(int j=(i==1);j<a[i];j++){
            y=trans[x][j];
            for(int k=0;k<=K-(w+v[y]);k++){
                Plus(ans,f[a[0]-i][y][k]);
            }
        }
        x=trans[x][a[i]];
        w+=v[x];
    }
    if(flag){//上界有否取 
        if(w<=K) Plus(ans,1);
    }
    return ans;
}
int main(){
    read(n);read(m);read(K);
    read(a[0]);for(int i=1;i<=a[0];i++) read(a[i]);
    read(b[0]);for(int i=1;i<=b[0];i++) read(b[i]);
    for(int i=1,l;i<=n;i++) read(l),insert(l);
    build_AC();prep(max(a[0],b[0]));
    printf("%d\n",(work(b,1)-work(a,0)+mod)%mod);
    return 0;
}

 

 

posted @ 2017-05-15 21:19  神犇(shenben)  阅读(373)  评论(0编辑  收藏  举报