BZOJ 3530 数数 发表于 2017-01-09 | 更新于 2018-06-17 Link好题。 存在一处容易遗漏的细节: 若001∈S001 \in S001∈S,111合法。 出题人比较心软只卡了20pts。 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114//Code by Lucida#include<bits/stdc++.h>#define get(x) scanf("%d",&x)//#define debug(x) std::cout<<#x<<'='<<x<<std::endltemplate <class T> inline bool chkmx(T &a,const T &b){return a<b?a=b,1:0;}template <class T> inline bool chkmn(T &a,const T &b){return a>b?a=b,1:0;}const int MAXN=2000+10,P=1e9+7;//正整数namespace iAC{ const int SIZE=MAXN; const char SB='0',SE='9'; const int SIGMA=SE-SB+1; struct Node { Node *son[SIGMA],*fail,*last;int cnt; int g[MAXN][2],f[MAXN]; Node *&next(char c){return son[c-SB];} Node() { memset(son,0,sizeof(son));fail=last=0;cnt=0; memset(g,0,sizeof(g));memset(f,0,sizeof(f)); } }*POOL=(Node*)malloc(SIZE*sizeof(Node)),*ME=POOL,*root=new(ME++) Node; Node *newNode(){return new(ME++) Node;} void Insert(char *s) { Node *cur=root; for(int i=1,L=strlen(s+1);i<=L;i++) { if(!cur->next(s[i])) cur->next(s[i])=newNode(); cur=cur->next(s[i]); } cur->cnt++; } void Build() { static Node *Q[SIZE];int he=1,ta=0; root->fail=root; for(char c=SB;c<=SE;++c) if(!root->next(c)) root->next(c)=root; else { root->next(c)->fail=root; Q[++ta]=root->next(c); } while(he<=ta) { Node* cur=Q[he++]; for(char c=SB;c<=SE;++c) { Node *&son=cur->next(c); if(!son) son=cur->fail->next(c); else { son->fail=cur->fail->next(c); son->last=son->fail->cnt?son->fail:son->fail->last; Q[++ta]=son; } } } }}using namespace iAC;typedef long long LL;LL DP(char *N){ LL res=0;int L=strlen(N+1); root->f[0]=1; for(int i=1;i<L;i++) for(Node *ptr=POOL;ptr!=ME;++ptr) for(char c=i==1?'1':'0';c<='9';++c) if(!ptr->next(c)->cnt && !ptr->next(c)->last) (ptr->next(c)->f[i]+=ptr->f[i-1])%=P; //res累加f[all][0~L-1] root->g[0][0]=1; for(int i=1;i<=L;i++) for(Node *ptr=POOL;ptr!=ME;++ptr) for(char c=i==1?'1':'0';c<='9';++c) if(!ptr->next(c)->cnt && !ptr->next(c)->last) { if(c==N[i]) (ptr->next(c)->g[i][0]+=ptr->g[i-1][0])%=P; else if(c<N[i]) (ptr->next(c)->g[i][1]+=ptr->g[i-1][0])%=P; (ptr->next(c)->g[i][1]+=ptr->g[i-1][1])%=P; } for(Node *ptr=POOL;ptr!=ME;++ptr) { (res+=ptr->g[L][0]+ptr->g[L][1])%=P; for(int i=1;i<L;i++) (res+=ptr->f[i])%=P; } return res;}int main(){ static char N[MAXN],str[MAXN]; scanf("%s",N+1); int m;get(m); for(int i=1;i<=m;i++) { scanf("%s",str+1); Insert(str); } Build(); LL ANS=DP(N); printf("%lld\n",ANS); return 0;}/* AC Record(Bugs) * * WA Naive.Detail ignored. MLE LL Array MAXN to large NOT WA BUT next->last!!! * * * * * * * * * */