AC自动机+数位DP, 记忆化搜索求数位DP比较特别
#include <algorithm>
#include <cstring>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stdlib.h>
using namespace std;
const int MOD = 1000000009;
const int SZ = 2;
int ch[2005][SZ], val[2005], fail[2005], sz; //ch是字典树, val[i]表示以i为结束的id
bool vis[2005];
int bcd[2005][10];
void build(char *s)
{
int len = strlen(s), u, r, i;
r = 0;
for(i=0;i<len;i++){
u = s[i]-'0';
if(!ch[r][u]){
ch[r][u] = ++sz;
memset(ch[sz], 0, sizeof(ch[sz]));
}
int tp = r;
r = ch[r][u];
vis[r] |= vis[tp];
}
vis[r] = 1;
}
void make_fail()
{
int i, j;
queue<int>q;
fail[0] = 0;
for(i=0;i<SZ;i++){
if(ch[0][i]) q.push(ch[0][i]), fail[ch[0][i]] = 0;
}
int cur, r;
while(!q.empty()){
cur = q.front(), q.pop();
for(i=0;i<SZ;i++){
r = ch[cur][i];
if(r){
fail[r] = ch[fail[cur]][i];
vis[r] |= vis[fail[r]];
q.push(r);
}else {
ch[cur][i] = ch[fail[cur]][i];
}
}
}
}
char A[2005], B[2005];
int num[2005];
char str[33];
int dp[205][2005];
int va[2005];
int chg(int cur,int va)
{
int i, it;
if(vis[cur]) return -1;
int tp = va;
for(i=3;i>=0;i--){
it = (va>>i)&1;
cur = ch[cur][it];
if(vis[cur]) return -1;
}
return cur;
}
void init()
{
int i, j;
for(i=0;i<=sz;i++) for(j=0;j<10;j++) bcd[i][j]=chg(i,j);
}
long long calc(int pos,int sta,bool st,bool sm)
{
if(pos == -1) return 1;
if(sm && st && dp[pos][sta] != -1) {
return dp[pos][sta];
}
long long ret = 0;
if(st){
if(bcd[sta][0] != -1)
ret += calc(pos-1, bcd[sta][0], st, sm||(0<va[pos])), ret %= MOD;
}else {
ret += calc(pos-1, 0, 0, sm||(0<va[pos]));
ret %= MOD;
}
int lim = va[pos];
if(sm) lim = 9;
int i;
for(i=1; i<=lim; i++){
if(bcd[sta][i] != -1)
{
ret += calc(pos-1, bcd[sta][i], 1, sm||(i<lim));
ret %= MOD;
}
}
if(sm && st) dp[pos][sta] = ret;
return ret;
}
int main()
{
int i, j, n, T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(vis, 0, sizeof(vis));
memset(ch[0], 0, sizeof(ch[0]));
sz = 0;
for(i=1; i<=n; i++){
scanf("%s",str);
build(str);
}
make_fail();
init();
scanf("%s",A);
int len = strlen(A);
for(i=len-1; i>=0; i--){
if(A[i]=='0') A[i] = '9';
else {
A[i]--;
break;
}
}
for(i=0; i<len; i++) va[i] = A[len-i-1] - '0';
long long ans1, ans2;
memset(dp, -1, sizeof(dp));
ans1 = calc(len-1, 0, 0, 0);
scanf("%s",B);
len = strlen(B);
for(i=0; i<len; i++) va[i] = B[len-i-1] - '0';
ans2 = calc(len-1, 0, 0, 0);
printf("%lld\n",(MOD + ans2 - ans1)%MOD);
}
return 0;
}