zoj 3494
数位dp+ac自动机
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define mod 1000000009 #define N 2010 typedef long long ll; using namespace std; char s[210]; int next[N][2],nextd[N][10],pos,flag[N],fail[N]; ll dp[210][N]; int newnode(){ memset(next[pos],0,sizeof(next[pos])); memset(nextd[pos],0,sizeof(nextd[pos])); flag[pos]=fail[pos]=0; return pos++; } void insert(){ int p=0,i; for(i=0;s[i];i++){ int k=s[i]-'0'; p=next[p][k]?next[p][k]:next[p][k]=newnode(); } flag[p]=1; } void makefail(){ queue<int>q; q.push(0); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<2;i++){ int v=next[u][i]; if(v==0) next[u][i]=next[fail[u]][i]; else q.push(v); if(u&&v){ fail[v]=next[fail[u]][i]; flag[v]|=flag[fail[v]]; } } } } void makenext(){ int tem,i,j,k; for(i=0;i<pos;i++){ for(j=0;j<10;j++){ if(flag[i]==0){ tem=i; //在这wa死了 for(k=3;k>=0;k--){ //在这wa死了 if(j&(1<<k)){ tem=next[tem][1]; } else{ tem=next[tem][0]; } if(flag[tem]==1)break; } if(k==-1) nextd[i][j]=tem; else nextd[i][j]=-1; } else nextd[i][j]=-1; } } } void pre(){ int len=strlen(s),i,j; for(i=0;i<len;i++) if(s[i]!='0')break; if(i==0)return; for(j=i,i=0;j<len;j++,i++) s[i]=s[j]; s[i]='\0'; } void minus_one(){ int len=strlen(s),i; for(i=len-1;i>=0;i--){ if(s[i]>'0'){ s[i]--; return ; } else s[i]='9'; } } /*ll dfs(int pos,int sta,int pre,int doing){ //不需要存储前面都是0的解,因为只会用到一次,dp少开一维 if(!s[pos]) return 1; if(!doing && pre && dp[pos][sta]!=-1) return dp[pos][sta]; ll ans=0; int i,end; if(doing)end=s[pos]-'0'; else end=9; if(pre==0) ans=dfs(pos+1,0,0,0)%mod; else{ if(nextd[sta][0]!=-1) ans=(ans+dfs(pos+1,nextd[sta][0],1,(doing && (i==end))))%mod; } for(i=1;i<=end;i++){ if(nextd[sta][i]==-1)continue; ans=(ans+dfs(pos+1,nextd[sta][i],1,(doing && (i==end))))%mod; } if(!doing && pre){ dp[pos][sta]=ans; } return ans; } ll solve(){ memset(dp,-1,sizeof(dp)); return dfs(0,0,0,1); }*/ ll dfs(int pos,int sta,int first,int doing){ if(!s[pos]) return 1; if(!doing && !first && dp[pos][sta]!=-1) return dp[pos][sta]; ll ans=0; int i,end; if(doing)end=s[pos]-'0'; else end=9; for(i=first;i<=end;i++){ if(nextd[sta][i]==-1)continue; //ans=(ans+dfs(pos+1,nextd[sta][i],0,(doing && (i==end))))%mod; ans+=dfs(pos+1,nextd[sta][i],0,(doing && (i==end))); if(ans>=mod)ans-=mod; } if(!doing && !first){ dp[pos][sta]=ans; } return ans; } ll solve(){ ll ans=0; memset(dp,-1,sizeof(dp)); for(int i=0;s[i];i++){ //这样写是枚举长度,注意这里没有算上0 //ans=(ans+dfs(i,0,1,i==0))%mod; ans+=dfs(i,0,1,i==0); if(ans>=mod) ans-=mod; } return ans; } int main(){ int t,T,n,i,j; scanf("%d",&T); for(t=1;t<=T;t++){ scanf("%d",&n); pos=0,newnode(); for(i=1;i<=n;i++){ scanf("%s",s); insert(); } makefail(); makenext(); scanf("%s",s); pre(); minus_one(); ll ans1=solve(); scanf("%s",s); pre(); ll ans2=solve(); printf("%lld\n",(ans2-ans1+mod)%mod); } return 0; }