http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494
这题没什么好说的,就是数位DP,用AC自动机预处理一下就行了
总体来说还是很裸的,但是有点恶心,还要高精度
//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
/************************************************
Code By willinglive Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=(l),___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=(r),___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
/
int n;
char str[222];
struct node{
node *next[2],*fail;
bool isword;int id;
void init(){next[0]=next[1]=fail=0; isword=0;}
}*root,T[20000];
int cntNode;
struct bign
{
int l;
char c[222];
bign(){MS(c,0);l=0;}
void read()
{
scanf("%s",str);
int len=strlen(str);
per(i,len-1,0) c[l++]=str[i]-'0';
}
void operator --()
{
c[0]--;
rep(i,0,l-1)
{
if(c[i]<0) c[i+1]--,c[i]+=10;
if(c[i+1]>=0) break;
}
while(l>1 && !c[l-1]) l--;
}
/*void print()
{
per(i,l-1,0) printf("%d",c[i]);
}*/
}A,B;
LL dp[202][2002][2];
int bit[222];
node* move[2002][10];
/
inline LL MOD(LL x){x%=1000000009;if(x<0)x+=1000000009;return x;}
node* newNode()
{
T[++cntNode].init();
T[cntNode].id=cntNode;
return &T[cntNode];
}
void insert(char *p)
{
node *o=root;
for(;*p;p++)
{
int son=*p-'0';
if(o->next[son]==0) o->next[son]=newNode();
o=o->next[son];
}
o->isword=1;
}
void ACMatch()
{
static queue<node*>q;
q.push(root); root->fail=0;
while(!q.empty())
{
node *o=q.front(); q.pop();
rep(i,0,1)
if(o->next[i])
{
if(o==root) o->next[i]->fail=root;
else
{
o->next[i]->fail=o->fail->next[i];
if(o->next[i]->fail->isword) o->next[i]->isword=1;
}
q.push(o->next[i]);
}
else if(o==root) o->next[i]=root;
else o->next[i]=o->fail->next[i];
}
}
node *get_move(node *t,int x)
{
rep(i,1,4) bit[i]=x&1,x>>=1;
node *o=t;
if(o->isword) return 0;
per(i,4,1)
{
if(o->next[bit[i]]->isword) return 0;
o=o->next[bit[i]];
}
return o;
}
void init_move()
{
rep(i,1,cntNode)
{
rep(j,0,9)
{
move[i][j]=get_move(&T[i],j);
}
}
}
LL dfs(int pos,node *o,bool limit,bool zero)
{
if(pos==0) return 1;
LL tmp=dp[pos][o->id][zero];
if(!limit&&tmp!=-1) return tmp;
LL ans=0;
int upp=limit?bit[pos]:9;
rep(i,0,upp)
{
int tmp=zero&&i==0;
if(!move[o->id][i]&&!tmp) continue;
ans+=dfs(pos-1,tmp?o:move[o->id][i],limit&&i==upp,tmp);
ans=MOD(ans);
}
if(!limit) dp[pos][o->id][zero]=ans;
return ans;
}
LL cal(const bign &x)
{
*bit=0;
rep(i,0,x.l-1) bit[++*bit]=x.c[i];
return dfs(*bit,root,1,1);
}
/
void input()
{
cntNode=0; A.l=B.l=0; MS(dp,-1);
n=read();
root=newNode();
rep(i,1,n)
{
scanf("%s",str);
insert(str);
}
A.read();
B.read();
--A;
}
void solve()
{
ACMatch();
init_move();
cout<<MOD(cal(B)-cal(A))<<endl;
}
/
int main()
{
#ifndef _TEST
freopen("std.in","r",stdin); freopen("std.out","w",stdout);
#endif
rep(i,1,read())
input(),solve();
return 0;
}