[数位DP AC自动机] Codeforces 434C Round #248 (Div. 1) C. Tachibana Kanade's Tofu

来源:互联网 发布:有关c语言的书籍 编辑:程序博客网 时间:2024/05/17 02:28

这个题无话可说
fi,j,k,t表示第 i 位,AC自动机上走到 j ,当前得分为 k ,是否小于上界 t
复杂度看着很高,其实跑不满?

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define cl(x) memset(x,0,sizeof(x))using namespace std;#define read(x) scanf("%d",&(x))const int N=205;int n,m,K;int ncnt=1,rt=1;int val[N];int ch[N][N];int fail[N];inline void insert(int *s,int n,int v){  int p=rt;  for (int i=1;i<=n;i++){    if (!ch[p][s[i]]) ch[p][s[i]]=++ncnt;    p=ch[p][s[i]];  }  val[p]+=v;}int Q[N],l,r;inline void Build(){  fail[rt]=rt; int u,v; l=r=-1;  for (int i=0;i<m;i++)    if (!ch[rt][i])      ch[rt][i]=rt;    else      v=ch[rt][i],fail[v]=rt,val[v]+=val[fail[v]],Q[++r]=v;  while (l<r){    int u=Q[++l];    for (int i=0;i<m;i++)      if (!ch[u][i])    ch[u][i]=ch[fail[u]][i];      else    v=ch[u][i],fail[v]=ch[fail[u]][i],val[v]+=val[fail[v]],Q[++r]=v;  }}const int P=1e9+7;inline void add(int &x,int y){  x+=y; if (x>=P) x-=P;}int f[N][N][505][2];inline int Solve(int n,int *a){  if (!n) return 0;  for (int i=0;i<n;i++){    for (int j=1;j<=ncnt;j++)      for (int k=0;k<=K;k++)    for (int t=0;t<2;t++)      if (f[i][j][k][t]){        int lim=t?m-1:a[i+1];        for (int r=0;r<=lim;r++){          int nt=t|(r<a[i+1]);          if (k+val[ch[j][r]]<=K)        add(f[i+1][ch[j][r]][k+val[ch[j][r]]][nt],f[i][j][k][t]);        }      }    for (int r=1;r<=((i+1==1)?a[i+1]:m-1);r++){      int nt=i+1==1?r<a[i+1]:1;      if (val[ch[rt][r]]<=K)    add(f[i+1][ch[rt][r]][val[ch[rt][r]]][nt],1);    }   }  int ans=0;  for (int j=1;j<=ncnt;j++)    for (int k=0;k<=K;k++)      for (int t=0;t<2;t++)    add(ans,f[n][j][k][t]);  return ans;}int nl,_l[N];int nr,_r[N];int len,s[N],vv;int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(m); read(K);  read(nl); for (int i=1;i<=nl;i++) read(_l[i]);  read(nr); for (int i=1;i<=nr;i++) read(_r[i]);  for (int i=1;i<=n;i++){    read(len); for (int j=1;j<=len;j++) read(s[j]); read(vv);    insert(s,len,vv);  }  Build();  int ans=Solve(nr,_r);  cl(f);  if (!(nl==1 && _l[1]==1)){    _l[nl]--;    for (int i=nl;i>1;i--)      if (_l[i]<0) _l[i]+=m,_l[i-1]--;    int t=1; while (_l[t]==0) t++; t--;    for (int i=t+1;i<=nl;i++)      _l[i-t]=_l[i];    nl-=t;    ans=(ans+P-Solve(nl,_l))%P;  }  printf("%d\n",ans);  return 0;}
原创粉丝点击