[ZOJ3494]BCD Code
AC自动机+数位DP。
大致题意:
BCD码就是把一个数十进制下的每一位分别用4位的二进制表示。
给你一坨01串,问你在一个区间内,有多少个数的BCD码不包含任何一个字符串。
因为涉及到多个串的匹配问题...所以要在AC自动机上DP
f[i][j]表示在自动机上的节点i,再往后走j步 的合法方案数。(合法就是说,经过的路径上不包含任何一个给定字符串)
建完AC自动机后,把非法的节点都删掉,再求出CH[i][j]表示从i节点出发,经过数字j后到达的节点(0<=j<=9),这样好转移= =。
一开始想写递归版本的。。前导0什么的完全无力TAT
后来干脆用记忆化搜索求f数组,然后统计答案的时候用正常姿势。。这样好写多了>_<
结果交完直接#1了。。我是没看出来自己的写法哪里常数优越= =
其实这题只比普通模版题多了个AC自动机而已。。。其他甚至还简单点
就算是递归版的,只要好好想一下前导零的问题就行了吧...网上递归版的标程也不长
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int modd=;
int fail[],ch[][];
int CH[][];
int f[][],u[][];//f[i][j]在自动机上的i节点时,再往后走j步的合法方案数
int i,j,k,n,m,tot,T,ans,len;
bool gg[]; char s[];int dl[]; inline void insert(int len){
int i,now=;
for(i=;i<len;i++)
s[i]-='',now=ch[now][s[i]]?ch[now][s[i]]:(ch[now][s[i]]=++tot);
gg[now]=;
}
inline void build(){
int l=,r=,i,now,tmp;
while(l<r){
now=dl[++l];
for(i=;i<=;i++)if(ch[now][i]){
for(tmp=fail[now];tmp&&!ch[tmp][i];tmp=fail[tmp]);
fail[ch[now][i]]=(now==)?:ch[tmp][i]; gg[ch[now][i]]|=gg[fail[ch[now][i]]]|gg[now];
dl[++r]=ch[now][i];
}else{
for(tmp=fail[now];tmp&&!ch[tmp][i];tmp=fail[tmp]);
ch[now][i]=ch[tmp][i];
}
}
for(i=;i<=tot;i++)for(j=;j<=;j++)if(gg[ch[i][j]]||gg[i])ch[i][j]=-;
for(i=;i<=tot;i++)if(!gg[i])
for(j=;j<=;j++){
for(now=i,k=;k&&now!=-;k>>=)
now=ch[now][(k&j)!=];
CH[i][j]=now;//printf(" %d->%d %d\n",i,j,CH[i][j]);
}
for(i=;i<=tot;i++)if(!gg[i])f[i][]=,u[i][]=T;
}
inline int dfs(int x,int step){
if(u[x][step]==T)return f[x][step];
int ans=;
for(int i=;i<=;i++)if(CH[x][i]!=-)
ans+=dfs(CH[x][i],step-),ans-=ans>=modd?modd:;
u[x][step]=T,f[x][step]=ans;//printf(" f: %d %d %d\n",x,step,f[x][step]);
return ans;
}
inline int get(int len){//求区间[1,len)内合法方案数
register int i,j,ans=,now;
for(i=;i<len;i++)s[i]-=;
for(i=;i<len;i++)for(j=;j<=;j++)if(CH[][j]!=-)
ans+=dfs(CH[][j],i-),ans-=ans>=modd?modd:;
for(i=;i<s[];i++)if(CH[][i]!=-)ans+=dfs(CH[][i],len-),ans-=ans>=modd?modd:; now=CH[][s[]];
for(i=;i<len&&now!=-;i++){
for(j=;j<s[i];j++)if(CH[now][j]!=-)ans+=dfs(CH[now][j],len-i-),ans-=ans>=modd?modd:;
now=CH[now][s[i]];
}
return ans;
}
inline void add(){
int i,j;
for(i=len-;i>=;i--)if(s[i]!='')break;
if(i>=)
for(s[i]++,j=i+;j<len;j++)s[j]='';
else{
for(s[]='',i=;i<=len;i++)s[i]='';
len++;
}
}
int main(){
for(scanf("%d",&T);T;T--){
scanf("%d",&n);memset(gg,,tot+);memset(ch,,(tot+)<<);tot=;
for(i=;i<=n;i++)
scanf("%s",s),insert(strlen(s));
build();
scanf("%s",s);len=strlen(s);ans=-get(len);
scanf("%s",s);len=strlen(s);add();ans+=get(len);
if(ans<)ans+=modd;
printf("%d\n",ans);
}
return ;
}
[ZOJ3494]BCD Code的更多相关文章
- zoj3494 BCD Code(AC自动机+数位dp)
Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is represented by ...
- ZOJ 3494 BCD Code(AC自动机+数位DP)
BCD Code Time Limit: 5 Seconds Memory Limit: 65536 KB Binary-coded decimal (BCD) is an encoding ...
- ZOJ 3494 BCD Code (AC自己主动机 + 数位DP)
题目链接:BCD Code 解析:n个病毒串.问给定区间上有多少个转换成BCD码后不包括病毒串的数. 很奇妙的题目. . 经典的 AC自己主动机 + 数位DP 的题目. 首先使用AC自己主动机,得到b ...
- BCD Code ZOJ - 3494 AC自动机+数位DP
题意: 问A到B之间的所有整数,转换成BCD Code后, 有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000. BCD码这个在数字电路课上讲了, ...
- zoj 3494:BCD Code
Description Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is rep ...
- ZOJ 3494 BCD Code (数位DP,AC自动机)
题意: 将一个整数表示成4个bit的bcd码就成了一个01串,如果该串中出现了部分病毒串,则是危险的.给出n个病毒串(n<=100,长度<21),问区间[L,R]中有几个数字是不含病毒串的 ...
- ZOJ 3494 BCD Code(AC自动机 + 数位DP)题解
题意:每位十进制数都能转化为4位二进制数,比如9是1001,127是 000100100111,现在问你,在L到R(R <= $10^{200}$)范围内,有多少数字的二进制表达式不包含模式串. ...
- FZU 2113 BCD Code 数位dp
数位dp,但是很奇怪的是我在虚拟oj上用GUC C++提交会wa,用Visual c++提交正确,但是加上注释后提交又莫名CE--好任性啊 0 ,0 题目思路:看代码吧 注释很详细 #include& ...
- [转]数位dp小记
转载自:http://blog.csdn.net/guognib/article/details/25472879 参考: http://www.cnblogs.com/jffifa/archive/ ...
随机推荐
- Parallels Desktop 12 for Mac 破解版
Parallels Desktop for Mac 是功能最强大灵活度最高的虚拟化方案,无需重启即可在同一台电脑上随时访问Windows和Mac两个系统上的众多应用程序.从仅限于PC的游戏到生产力软件 ...
- webpack 3.X学习之多页面打包
简介 我们开发不可能只写一个页面,每次都要写很多页面,这时为了开发效率,我们使用前端自动化工具webpack,那么webpack是如何打包页面的呢?又是如何打包多页面的呢? 单页面打包 我们知道要打包 ...
- Scala 安装 Exception in thread "main" java.lang.VerifyError: Uninitialized object exists on backward branch 96
windows下载安装完最新版本的Scala(2.12.4)后,终端如下错误 C:\Users\Administrator>scala -versionException in thread & ...
- 基于Java Mail 进行发送(带附件和压缩附件)的邮件
刚进公司的training, 下面是要求: Self-study of Java Mail library: http://www.oracle.com/technetwork/java/javam ...
- 安装spark单机环境
(假定已经装好的hadoop,不管你装没装好,反正我是装好了) 1 下载spark安装包 http://spark.apache.org/downloads.html 下载spark-1.6.1-bi ...
- 例子:韩顺平JavaScript----JS乌龟抓小鸡游戏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- libcurl的使用
http://blog.csdn.net/ixiaochouyu/article/details/47998267
- ADO.NET访问数据库
1:ADO.NET数据库的方法和技术 2:ADO.NET的主要组成: 1>DataSet(数据集)-----独立于数据间的数据访问 2>.NETFramework(数据提供程序)----- ...
- 高效的CSS代码(2)
——阅读笔记,欢迎纠错^_^ 内容比较零散..... 1.让浮动元素的父容器根据元素的高度而自适应高度的方法: <div class="clearfix"><di ...
- 通过pyenv和virtualenv创建多版本Python虚拟环境
虚拟环境使用第三方工具virtualenv创建,首先输入以下命令检查系统是否已经安装virtualenv. $ virtualenv --version 如果显示virtualenv版本号,则说明已经 ...