题目链接:  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494

题目大意:给定一些被禁止的BCD码。问指定范围内不含有任何这些禁止的BCD码的数的个数。

解题思路

AC自动机部分:

首先insert这些被禁止的BCD码。

然后打一下自动机前后状态的转移的表,用BCD[i][j]表示自动机状态i时,下一个数字是j的自动机的下一个状态。

一开始我考虑最先dfs的位在自动机的位置,后来发现SB了。AC自动机有一个root状态,也就是自动机位置为0的状态,使用这个0就行了。

即f函数中dfs(len,0,true,true),每次由root状态出发,无须再考虑其它的。

数位DP部分:

本题的范围是高精度范围,所以需要特有的高精度写法。

麻烦的在于f(l-1),要为高精度手艹一个-1,有种偷懒的写法,不过会导致出现前导0。

所以在传统的dfs中需要增加一个前导0的判断。

方法是:追加一个bool z,

在原有的0~9基础上,单独考虑0,

if(z) 则单独dfs前导0

否则dfs正常的0,1~9照常dfs。当然还需要判断当前状态s的下一个状态BCD[s][i]是否符合要求。

然后最后就是注意一下负数mod。

#include "cstdio"
#include "cstring"
#include "queue"
#include "iostream"
using namespace std;
#define maxp 25*105
#define mod 1000000009
struct Trie
{
Trie *next[],*fail;
int cnt;
}pool[maxp],*root,*sz;
int BCD[maxp][],digit[],ccnt;
long long dp[][maxp];
Trie *newnode()
{
Trie *ret=sz++;
memset(ret->next,,sizeof(ret->next));
ret->fail=;
ret->cnt=;
return ret;
}
void init()
{
sz=pool;
root=newnode();
}
void Insert(string str)
{
Trie *pos=root;
for(int i=;i<str.size();i++)
{
int c=str[i]-'';
if(!pos->next[c]) pos->next[c]=newnode();
pos=pos->next[c];
}
pos->cnt++;
}
void getfail()
{
queue<Trie *> Q;
for(int c=;c<;c++)
{
if(root->next[c])
{
root->next[c]->fail=root;
Q.push(root->next[c]);
}
else root->next[c]=root;
}
while(!Q.empty())
{
Trie *x=Q.front();Q.pop();
for(int c=;c<;c++)
{
if(x->next[c])
{
x->next[c]->fail=x->fail->next[c];
x->next[c]->cnt+=x->fail->next[c]->cnt;
Q.push(x->next[c]);
}
else x->next[c]=x->fail->next[c];
}
}
}
int judge(int status,int num)
{
Trie *pos=pool+status;
if(pos->cnt) return -;
for(int i=;i>=;i--)
{
if(pos->next[(num>>i)&]->cnt) return -;
else pos=pos->next[(num>>i)&];
}
return pos-pool;
}
void getbcd()
{
for(int i=;i<ccnt;i++)
for(int j=;j<;j++)
BCD[i][j]=judge(i,j);
}
int dfs(int len,int s,bool fp,bool z)
{
if(!len) return ;
if(!fp&&dp[len][s]!=-) return dp[len][s];
long long ret=;
int fpmax=fp?digit[len]:;
if(z)
{
ret+=dfs(len-,s,fp&&digit[len]==,true);
ret%=mod;
}
else
{
if(BCD[s][]!=-) ret+=dfs(len-,BCD[s][],fp&&digit[len]==,false);
ret%=mod;
}
for(int i=;i<=fpmax;i++)
{
if(BCD[s][i]!=-) ret+=dfs(len-,BCD[s][i],fp&&i==fpmax,false);
ret%=mod;
}
if(!fp&&!z) dp[len][s]=ret;
return ret;
}
int f(string str)
{
int len=;
for(int i=str.size()-;i>=;i--)
digit[++len]=str[i]-'';
return dfs(len,,true,true);
}
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int T,n;
string tt;
cin>>T;
while(T--)
{
init();
memset(dp,-,sizeof(dp));
cin>>n;
for(int i=;i<=n;i++)
{
cin>>tt;
Insert(tt);
}
getfail();
ccnt=sz-pool;
getbcd();
cin>>tt;
for(int i=tt.size()-;i>=;i--)
{
if(tt[i]>'') {tt[i]--;break;}
else {tt[i]='';}
}
long long ans=;
ans-=f(tt);
ans%=mod;
cin>>tt;
ans+=f(tt);
ans=(ans%mod+mod)%mod;
printf("%lld\n",ans);
}
}
2842327 neopenx ZOJ 3494 Accepted 4656 KB 210 ms C++ (g++ 4.4.5) 2976 B 2014-10-13 17:06:35

ZOJ 3494 (AC自动机+高精度数位DP)的更多相关文章

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

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

  2. ZOJ 3494 BCD Code (数位DP,AC自动机)

    题意: 将一个整数表示成4个bit的bcd码就成了一个01串,如果该串中出现了部分病毒串,则是危险的.给出n个病毒串(n<=100,长度<21),问区间[L,R]中有几个数字是不含病毒串的 ...

  3. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

  4. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. [bzoj3530][Sdoi2014]数数_AC自动机_数位dp

    数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...

  6. HDU4758 Walk Through Squares(AC自动机+状压DP)

    题目大概说有个n×m的格子,有两种走法,每种走法都是一个包含D或R的序列,D表示向下走R表示向右走.问从左上角走到右下角的走法有多少种走法包含那两种走法. D要走n次,R要走m次,容易想到用AC自动机 ...

  7. POJ1699 Best Sequence(AC自动机+状压DP)

    题目,求包含所有的给定的n个DNA片段的序列的最短长度. AC自动机上的DP题. dp[S][u]表示已经包含的DNA片段集合为S,且当前后缀状态是自动机第u个结点的最短长度 dp[0][0]=0 我 ...

  8. HDU 4511 (AC自动机+状态压缩DP)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...

  9. POJ 3691 (AC自动机+状态压缩DP)

    题目链接:  http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...

随机推荐

  1. [BZOJ2959]长跑——新技能:LCT+缩圈

    [BZOJ2959]长跑 试题描述 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上熙熙攘攘 ...

  2. Awvs如何扫描需要登录的部分

    一个小技巧,可能部分的人习惯了按下一步.所以不大知道.给大家说说哈. 到LOGIN步骤的时候,在Login sequen 新建.然后你懂的了.会新出来一个浏览器,直接登录后一直下一步即可

  3. k-means

    参考:http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006910.html k-means是无监督的聚类算法,比较简单,但包含的思想不简单, ...

  4. 发个题目坑 二模03day1

    1.数列(seq2.pas/c/cpp) 题目描述 一个数列定义如下:f(1) = 1,f(2) = 1,f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.给定 A ...

  5. static-const 类成员变量

    [本文链接] http://www.cnblogs.com/hellogiser/p/static-const.html [分析] const数据成员必须在构造函数初始化列表中初始化; static数 ...

  6. canva实践小实例 —— 马赛克效果

    前面给大家带来了操作像素的API,此时此刻,我觉得应该配以小实例来进行进一步的说明和演示,以便给大家带来更宽广的视野和灵感,你们看了我的那么多的文章,应该是懂我的风格,废话不多说,进入正题: 这次给大 ...

  7. NEFU 1146 又见A+B

    又见a+b Problem:1146 Time Limit:1000ms Memory Limit:65535K Description 给定两个非负整数A,B,求他们的和. Input 多组输入,每 ...

  8. PO/VO/BO等对象模型

    PO :persistent object持久对象 1 .有时也被称为Data对象,对应数据库中的entity,可以简单认为一个PO对应数据库中的一条记录. 2 .在hibernate持久化框架中与i ...

  9. IDE整理

    1.eclipse 下载地址:http://www.eclipse.org/downloads/     2.myeclipse 下载地址:http://www.myeclipseide.com/mo ...

  10. vm 负责虚拟机出现“”适配器 的mac地址在保留地址范围内‘’

    我自己在windows中文件中,直接将一个虚拟机进行复制了一份,后用vm打开, 选择我已经移到,结果会出现了一下的情况, 导致了我无法ping 通,故我看到一下提示: 原来是我两台虚拟机的MaC ,即 ...