题目链接:BCD Code

解析:n个病毒串。问给定区间上有多少个转换成BCD码后不包括病毒串的数。

很奇妙的题目。

经典的 AC自己主动机 + 数位DP 的题目。

首先使用AC自己主动机,得到bcd[i][j]表示状态i,加了数字j以后到达的状态。为-1表示不能转移

然后就是数位DP了



注意记录为0的状态

AC代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; struct Trie{
int next[2010][2], fail[2010];
bool end[2010];
int root, L;
int newnode(){
for(int i=0; i<2; i++) next[L][i] = -1;
end[L++] = false;
return L-1;
}
void init(){
L = 0;
root = newnode();
}
void insert(char buf[]){
int len = strlen(buf);
int now = root;
for(int i=0; i<len; i++){
if(next[now][buf[i] - '0'] == -1)
next[now][buf[i] - '0'] = newnode();
now = next[now][buf[i] - '0'];
}
end[now] = true;
}
void build(){
queue<int> Q;
fail[root] = root;
for(int i=0; i<2; 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();
if(end[ fail[now] ]) end[now] = true;
for(int i=0; i<2; 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]);
}
}
}
}; Trie ac;
char buf[210]; int bcd[2010][10];
int change(int pre, int num){
if(ac.end[pre]) return -1;
int cur = pre;
for(int i=3; i>=0; i--){
if(ac.end[ac.next[cur][(num>>i)&1]]) return -1;
cur = ac.next[cur][(num>>i)&1];
}
return cur;
}
void pre_init(){
for(int i=0; i<ac.L; i++)
for(int j=0; j<10; j++)
bcd[i][j] = change(i, j);
}
const int MOD = 1000000009;
long long dp[210][2010];
int bit[210]; long long dfs(int pos, int s, bool flag, bool z){
if(pos == -1) return 1;
if(!flag && dp[pos][s] != -1) return dp[pos][s];
long long ans = 0;
if(z){
ans += dfs(pos-1, s, flag && bit[pos] == 0, true);
ans %= MOD;
}
else{
if(bcd[s][0] != -1) ans += dfs(pos-1, bcd[s][0], flag && bit[pos] == 0, false);
ans %= MOD;
}
int _end = (flag ? bit[pos] : 9);
for(int i=1; i<=_end; i++){
if(bcd[s][i] != -1){
ans += dfs(pos-1, bcd[s][i], flag && i == _end, false);
ans %= MOD;
}
}
if(!flag && !z) dp[pos][s] = ans;
return ans;
} long long calc(char s[]){
int len = strlen(s);
for(int i=0; i<len; i++) bit[i] = s[len-1 - i] - '0';
return dfs(len-1, 0, true, true);
} int main(){
#ifdef sxk
freopen("in.txt", "r", stdin);
#endif // sxk
int T;
int n;
scanf("%d", &T);
while(T--){
ac.init();
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%s", buf);
ac.insert(buf);
}
ac.build();
pre_init();
memset(dp, -1, sizeof(dp));
int ans = 0;
scanf("%s", buf);
int len = strlen(buf);
for(int i=len-1; i>=0; i--){
if(buf[i] > '0'){
buf[i] --;
break;
}
else buf[i] = '9';
}
ans -= calc(buf);
ans %= MOD;
scanf("%s", buf);
ans += calc(buf);
ans %= MOD;
if(ans < 0) ans += MOD;
printf("%d\n", ans);
}
return 0;
}

ZOJ 3494 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. [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem

    意甲冠军: 给n快报,和m频率. 然后进入n字母出现的概率 然后给目标字符串str 然后问m概率倍的目标字符串是敲数量. 思维: AC自己主动机+可能性dp简单的问题. 首先建立trie图,然后就是状 ...

  3. POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)

    http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...

  4. HDU 2825 Wireless Password (AC自己主动机,DP)

    pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...

  5. POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)

    题目链接:Censored! 解析:AC自己主动机 + 高精度 + 简单DP. 字符有可能会超过128.用map映射一下就可以. 中间的数太大.得上高精度. 用矩阵高速幂会超时,简单的DP就能解决时间 ...

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

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

  7. zoj 3494:BCD Code

    Description Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is rep ...

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

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

  9. hdu 2825 Wireless Password(ac自己主动机&amp;dp)

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

随机推荐

  1. 利用反射api查找一个类的具体信息

    讲到这个实例,首先介绍下本人,我是一个php程序猿.从事drupal开发2年多.能够说从实习開始就接触这个,至今没有换过.drupal给我的感觉是俩字"强大",今天写一个views ...

  2. USACO holstein 超时代码

    /* ID:kevin_s1 PROG:holstein LANG:C++ */第八组数据跪了.半天都不出结果 #include <iostream> #include <cstdi ...

  3. 【剑指Offer学习】【面试题26:复杂链表的复制】

    题目:请实现函数ComplexListNode clone(ComplexListNode head),复制一个复杂链表. 在复杂链表中,每一个结点除了有一个next 域指向下一个结点外,另一个sib ...

  4. keras中使用预训练模型进行图片分类

    keras中含有多个网络的预训练模型,可以很方便的拿来进行使用. 安装及使用主要参考官方教程:https://keras.io/zh/applications/   https://keras-cn. ...

  5. 38.Qt模型/视图结构

    1.模型/视图类 2.模型 3.视图 4.代理 1 模型/视图类 InterView框架提供了一些可以直接使用的模型类和视图类,如QStandardModel类,QDirModel类,QStringL ...

  6. Spark编程模型几大要素

    不多说,直接上干货! Spark编程模型几大要素 Driver Program 输入-Transformation-Action 缓存 共享变量

  7. Tarjan 求图点强联通,桥的应用

    在图中求双联通和强联通分量是我们解决非树结构的图连通问题的利器 通过求求图的双联通和强联通分量能把图转化成DAG进行求解: 行走 Description 给出一个有向图,你可以选择从任意点出发走到任意 ...

  8. wechat4j开发所有jar包

    wechat4j开发所需要的jar包合计,不用你去单独下载,已经全部包括 下载连接 wechat4j-lib.rar 如果你的服务是部署在新浪云计算SAE上的,那么下载这个jar合集 wechat4j ...

  9. Haskell手撸Softmax回归实现MNIST手写识别

    Haskell手撸Softmax回归实现MNIST手写识别 前言 初学Haskell,看的书是Learn You a Haskell for Great Good, 才刚看到Making Our Ow ...

  10. swift使用查阅资料备份1

    SnapKit RxSwift R.swift https://www.jianshu.com/p/68e12b966d86 iOS - RxSwift 项目实战记录 https://blog.csd ...