题意:有T组测试数据每组一个整数n代表有n个不合格的二进制编码,将所有数字转化为BCD码 判断区间l,r之间有多少合格的数字 (一个数只要转化为BCD码后中间有不合格的BCD码该数据就不合格)
题解:先用AC自动机将不合格二进制串处理好然后定义一个bcd[i][j]二维数组 表示在数字中前一个数为AC自动机树上的节点i时下一个位数为j(0~9)时合不合法 为-1表示不合法;
dp[i][j] 表示数字的第几位 j表示前一个数为AC自动机树上的节点i时有多少合格的数
(借鉴于大佬)代码:
题解:先用AC自动机将不合格二进制串处理好然后定义一个bcd[i][j]二维数组 表示在数字中前一个数为AC自动机树上的节点i时下一个位数为j(0~9)时合不合法 为-1表示不合法;
dp[i][j] 表示数字的第几位 j表示前一个数为AC自动机树上的节点i时有多少合格的数
(借鉴于大佬)代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
using namespace std;
#define clr(a,b) memset(a,b,sizeof(a))
#define reg register
#define il inline
typedef long long ll;
const int maxn = 2005;
const int mod= 1000000009;
char str[205];
class AC {
public:
int next[maxn][3], fail[maxn], tag[maxn];
int dig[205],bcd[maxn][10];
int root, tot;
ll dp[205][maxn];
void init() {
clr(dp,-1);
clr(next,-1);
clr(tag,0);
root =tot=0;
}
void insert(char *buf) {
int len = strlen(buf);
int now = root;
for(reg int i = 0; i < len; ++i) {
int id = buf[i] - '0';
now=next[now][id]!=-1?next[now][id]:(next[now][id]=++tot);
}
tag[now] = 1;
}
void build() {
queue<int> q;
fail[root] = root;
for(reg int i = 0; i < 3; ++i) {
if(next[root][i] == -1) {
next[root][i] = root;
}
else {
fail[next[root][i]] = root;
q.push(next[root][i]);
}
}
while(!q.empty()) {
int now = q.front();
q.pop();
tag[now] |= tag[fail[now]];
for(reg int i = 0; i < 3; ++i) {
if(next[now][i] == -1) {
next[now][i] = next[fail[now]][i];
} else {
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
}
void getbcd() {
for(reg int i = 0; i <=tot; ++i) {
for(reg int j = 0; j < 10; ++j) {
bcd[i][j] = i;
if(tag[i])
bcd[i][j] = -1;
int now = i;
for(reg int k = 3; k >= 0; --k) {//从做到右匹配
int x = (j >> k) & 1;
if(tag[next[now][x]]) {
bcd[i][j] = -1;
break;
}
else bcd[i][j] = next[now][x];
now = next[now][x];
}
}
}
}
ll dfs(int pos, int cur, int limit, int nozero) {
if(pos == 0) return 1;
if(dp[pos][cur] != -1 && !limit && nozero) return dp[pos][cur];
ll res = 0;
for(reg int i = 0; i <= (limit ? dig[pos] : 9); ++i) {
if(!nozero && i == 0)
res += dfs(pos-1, cur, limit&&i==dig[pos], nozero);
else if(bcd[cur][i] != -1)
res += dfs(pos-1, bcd[cur][i],limit&&i==dig[pos],1);
res %= mod;
}
if(!limit && nozero) dp[pos][cur] = res;
return res;
}
ll solve(char *buf) {
int len = strlen(buf);
for(reg int i = 0; i < len; ++i) {
dig[len - i] = buf[i] - '0';
}
return dfs(len, root, 1, 0);
}
}ac;
il void dec(char *buf) {//左区间后移一位
int len = strlen(buf);
for(reg int i = len-1; i >= 0; --i) {
if(buf[i] > '0') {
buf[i] --;
return ;
}
else buf[i] = '9';
}
}
int main() {
int t,n;
scanf("%d",&t);
while(t--) {
ac.init();
scanf("%d",&n);
while(n--)
{
scanf("%s",str);
ac.insert(str);
}
ac.build();
ac.getbcd();
scanf("%s",str);
dec(str);
ll ans = ac.solve(str);
scanf("%s",str);
printf("%lld\n",(ac.solve(str)-ans+mod)%mod);
}
return 0;
}