Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is represented by its own binary sequence. To encode a decimal number using the common BCD encoding,
each decimal digit is stored in a 4-bit nibble:

Decimal:    0     1     2     3     4     5     6     7     8     9
BCD: 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001

Thus, the BCD encoding for the number 127 would be:

 0001 0010 0111

We are going to transfer all the integers from A to B, both inclusive, with BCD codes. But we find that some continuous bits, named forbidden code, may lead to errors.
If the encoding of some integer contains these forbidden codes, the integer can not be transferred correctly. Now we need your help to calculate how many integers can be transferred correctly.

Input

There are multiple test cases. The first line of input is an integer T ≈ 100 indicating the number of test cases.

The first line of each test case contains one integer N, the number of forbidden codes ( 0 ≤ N ≤ 100). Then N lines follow, each of which contains a 0-1 string
whose length is no more than 20. The next line contains two positive integers A and B. Neither A or B contains leading zeros and 0 < A ≤ B < 10200.

Output

For each test case, output the number of integers between A and B whose codes do not contain any of the N forbidden codes in their BCD codes. For the result
may be very large, you just need to output it mod 1000000009.

Sample Input

3
1
00
1 10
1
00
1 100
1
1111
1 100

Sample Output

3
9

98

题意:给出一些模式串,给出一个范围[A,B],求出区间内有多少个数,写成BCD之后,不包含模式串。

思路:先用AC自动机存下不符合的节点,然后预处理出bcd[i][j]表示ac自动机节点i走j这个数后的节点编号或者-1,然后用dp[i][j]表示前i位,当前ac节点为j的方案数。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 300050
#define maxnode 2050
#define MOD 1000000009
int bcd[maxnode][11]; //bcd[i][j]表示ac自动机状态i走j步后的状态 struct trie{
int sz,root,val[maxnode],next[maxnode][2],fail[maxnode];
int q[11111];
void init(){
int i;
sz=root=0;
val[0]=0;
for(i=0;i<2;i++){
next[root][i]=-1;
}
}
void charu(char *s){
int i,j,u=0;
int len=strlen(s);
for(i=0;i<len;i++){
int c=s[i]-'0';
if(next[u][c]==-1){
sz++;
val[sz]=0;
next[u][c]=sz;
u=next[u][c];
for(j=0;j<2;j++){
next[u][j]=-1;
}
}
else{
u=next[u][c];
}
}
val[u]=1;
} void build(){
int i,j;
int front,rear;
front=1;rear=0;
for(i=0;i<2;i++){
if(next[root][i]==-1 ){
next[root][i]=root;
}
else{
fail[next[root][i] ]=root;
rear++;
q[rear]=next[root][i];
}
}
while(front<=rear){
int x=q[front];
if(val[fail[x]]) //!!!!!
val[x]=1;
front++;
for(i=0;i<2;i++){
if(next[x][i]==-1){
next[x][i]=next[fail[x] ][i];
}
else{
fail[next[x][i] ]=next[fail[x] ][i];
rear++;
q[rear]=next[x][i];
} }
}
}
}ac; int change(int jiedian,int num)
{
int i,j,len=0;
int shu[10];
while(num){
shu[++len]=num%2;
num/=2;
}
while(len<4)shu[++len]=0;
for(i=4;i>=1;i--){
if(ac.val[ac.next[jiedian][shu[i] ] ]==1 )return -1;
else jiedian=ac.next[jiedian][shu[i] ];
}
return jiedian;
} void pre_init()
{
int i,j;
for(i=0;i<=ac.sz;i++){
for(j=0;j<=9;j++){
bcd[i][j]=change(i,j);
}
}
} int wei[300];
ll dp[300][maxnode]; ll dfs(int pos,int jiedian,int lim,int zero)
{
int i,j;
if(pos==-1)return 1;
if(lim==0 && zero==0 && dp[pos][jiedian]!=-1){ //这里和下面同理,也不要省略zero==0
return dp[pos][jiedian];
}
int ed=lim?wei[pos]:9;
ll ans=0;
for(i=0;i<=ed;i++){
if(i==0){
if(zero){
ans+=dfs(pos-1,jiedian,0,1);
ans%=MOD;
}
else{
if(bcd[jiedian][0]!=-1){
ans+=dfs(pos-1,bcd[jiedian][0],lim&&i==ed,0);
ans%=MOD;
}
}
continue;
}
if(bcd[jiedian][i]!=-1){
ans+=dfs(pos-1,bcd[jiedian][i],lim&&i==ed,0);
ans%=MOD;
}
}
if(lim==0 && zero==0 ){ //这里要注意,不能写成if(lim==0)dp[pos][jiedian]=ans;因为zero不为0的话,即最高位还没有确定,那么可能后面几位都可以跳过去,
dp[pos][jiedian]=ans; //即可以把0跳过,但是对于最高位确定的情况下,后面不管加什么数都不能跳过去,即使是0也要在ac自动机上走0这个数.
}
return ans;
} ll cal(char *s)
{
int i,j,len;
len=strlen(s);
for(i=0;i<len;i++){
wei[i]=s[len-1-i]-'0';
}
return dfs(len-1,0,1,1);
} char s1[300],s2[300],s[30];
int main()
{
int n,m,i,j,T,len1,len2;
scanf("%d",&T);
while(T--)
{
ac.init();
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",s);
ac.charu(s);
}
ac.build();
pre_init();
scanf("%s",s1);
len1=strlen(s1);
reverse(s1,s1+len1);
for(i=0;i<len1;i++){ //这里算的是(l,r],所以先要把s1的数减去1
if(s1[i]-'0'>0){
s1[i]--;break;
}
else{
s1[i]='9';
}
}
memset(dp,-1,sizeof(dp));
ll ans=0;
if(s1[len1-1]=='0')len1-=1;
s1[len1]='\0';
reverse(s1,s1+len1);
ans-=cal(s1);
ans%=MOD;
scanf("%s",s2);
ans+=cal(s2);
ans%=MOD;
if(ans<0){
ans=(ans+MOD)%MOD;
}
printf("%lld\n",ans);
}
return 0;
}

zoj3494 BCD Code(AC自动机+数位dp)的更多相关文章

  1. ZOJ 3494 BCD Code(AC自动机+数位DP)

    BCD Code Time Limit: 5 Seconds      Memory Limit: 65536 KB Binary-coded decimal (BCD) is an encoding ...

  2. zoj3494BCD Code(ac自动机+数位dp)

    l链接 这题想了好一会呢..刚开始想错了,以为用自动机预处理出k长度可以包含的合法的数的个数,然后再数位dp一下就行了,写到一半发现不对,还要处理当前走的时候是不是为合法的,这一点无法移到trie树上 ...

  3. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  4. 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  5. BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)

    题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...

  6. BCD Code ZOJ - 3494 AC自动机+数位DP

    题意: 问A到B之间的所有整数,转换成BCD Code后, 有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000. BCD码这个在数字电路课上讲了, ...

  7. ZOJ 3494 BCD Code(AC自动机 + 数位DP)题解

    题意:每位十进制数都能转化为4位二进制数,比如9是1001,127是 000100100111,现在问你,在L到R(R <= $10^{200}$)范围内,有多少数字的二进制表达式不包含模式串. ...

  8. BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)

    Description 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3 ...

  9. 【JZOJ3624】【SDOI2014】数数(count) AC自动机+数位dp

    题面 100 容易想到使用AC自动机来处理禁忌子串的问题: 然后在自动机上数位dp,具体是: \(f_{i,j,0/1}\)表示填了\(i\)位,当前在自动机的第\(j\)个结点上,\(0\)表示当前 ...

随机推荐

  1. Java基础进阶类名整理

    类名综合 数学类: Math:数学运算 BigDecimal:用于精确计算数据 数组工具类: Arrays:数组工具类,用于对数组的操作 时间操作: JDK8以前: Date:表示一个时间,并面向对象 ...

  2. HAProxy-1.8.20 根据后缀名转发到后端服务器

    global maxconn 100000 chroot /data/soft/haproxy stats socket /var/lib/haproxy/haproxy.sock mode 600 ...

  3. pg_rman的安装与使用

    1.下载对应数据库版本及操作系统的pg_rman源码 https://github.com/ossc-db/pg_rman/releases 本例使用的是centos6.9+pg10,因此下载的是pg ...

  4. [usaco2008 Oct]Pasture Walking 牧场旅行

    题目描述 n个被自然地编号为1..n奶牛(1<=n<=1000)正在同样被方便的编号为1..n的n个牧场中吃草.更加自然而方便的是,第i个奶牛就在第i个牧场中吃草. 其中的一些对牧场被总共 ...

  5. [Usaco2007 Jan]Telephone Lines架设电话线

    题目描述 FarmerJohn打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务.于是,FJ必须为此向电信公司支付一定的费用.FJ的农场周围分布着N(1<=N<=1,000)根 ...

  6. OpenCV 和 Dlib 人脸识别基础

    00 环境配置 Anaconda 安装 1 下载 https://repo.anaconda.com/archive/ 考虑到兼容性问题,推荐下载Anaconda3-5.2.0版本. 2 安装 3 测 ...

  7. uni-app开发经验分享二十一: 图片滑动解锁插件制作解析

    在开发用户模块的时候,相信大家都碰到过一个功能,图片滑动解锁后发送验证码,这里分享我用uni-app制作的一个小控件 效果如下: 需要如下图片资源 template <template> ...

  8. VMware虚拟机提示“以独占方式锁定此配置文件失败”!!!

    VMware异常关闭后再次启动提示"以独占方式锁定此配置文件失败"!!! 前几日在使用VMware虚拟机的时候,虚拟机突然出现了卡顿,然后就把电脑关机了重启,结果再次打开虚拟机的时 ...

  9. jmeter跳过验证码登录配置:通过手动添加 Cookie 跳过带验证码的登录接口

    目录 一.基本配置 二.HTTP请求默认值 三.HTTP信息头管理器 四.HTTP Cookie管理器 五.线程组下接口设置 一.基本配置 二.HTTP请求默认值 (1)jmeter的设置: (2)设 ...

  10. 详解Mybatisplus

    详解Mybatisplus ​ MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生. 特性: 无侵入**:只 ...