【MZ】ZOJ 3494 BCD Code AC自动机+数位DP
来源:互联网 发布:javascript 基础 知乎 编辑:程序博客网 时间:2024/04/30 12:23
problem:
给你 n 个由 01 串组成的病毒。(0<=n<=100)
一个数的 BCD 编码为每个数字变成四位的二进制(如127 would be:0001 0010 0111)。
问从x到y有多少个数其BCD编码中没有病毒。(0<x<=y<10^(200))
think:
用 AC 自动机得到每个状态,每个状态是否已经构成一个病毒,每个状态后面加一个数字后转移到哪个状态。
有了这些处理,就是个简单的数位 DP 了。
CODE:
const int kind = 2;const LL mod = 1000000009;LL f[222][2222];//用于数位DPint bit[222];char ch[55], str[222];int fail[2222];//每个状态的fail指针int child[2222][2];//01两种int end[2222];//每个状态是否已经包含一整个病毒int dp[2222][12];//i状态后面加数字j变成dp[i][j]状态int cnt;//用于记录状态int newNode(){ ++cnt; child[cnt][0] = child[cnt][1] = -1; end[cnt] = 0; return cnt;}void insert(char *str, int root){ int p = root; for(int i=0; str[i]; ++i){ int k = str[i] - '0'; if(child[p][k] == -1) child[p][k] = newNode(); p = child[p][k]; } end[p] = 1;}//这个建立fail指针不同于hdu2222//这里的fail不能有空指针,必须要指向一个状态queue<int>q;void build_fail(int root){ while(!q.empty()) q.pop(); fail[root] = root; q.push(root); while(!q.empty()){ int tmp = q.front(); q.pop(); if(end[fail[tmp]]==1) end[tmp] = 1;//tmp也已经包括病毒 for(int k = 0; k < kind; ++k){ if(child[tmp][k]!=-1){ if(tmp==root) fail[child[tmp][k]] = root; else fail[child[tmp][k]] = child[fail[tmp]][k]; q.push(child[tmp][k]); } else { if(tmp==root) child[root][k] = root; else child[tmp][k] = child[fail[tmp]][k]; } } }}int change(int pre, int num){ if(end[pre]) return -1; int cur = pre; for(int i = 3; i >= 0; --i){ cur = child[cur][(num>>i)&1]; if(end[cur]) return -1; } return cur;}void init_dp(){ for(int i = 0; i <= cnt; ++i){ for(int j = 0; j < 10; ++j){ dp[i][j] = change(i, j); } }}LL dfs(int pos, int sta, bool e, bool z){ if(pos == 0) return 1LL; if(!e && ~f[pos][sta]) return f[pos][sta]; LL res = 0; if(z) res += dfs(pos-1, sta, e&&bit[pos]==0, true); else if(dp[sta][0]!=-1) res += dfs(pos-1, dp[sta][0], e&&bit[pos]==0, false); res %= mod; int u = e ? bit[pos] : 9; for(int d = 1; d <= u; ++d){ if(dp[sta][d]==-1) continue; res += dfs(pos-1, dp[sta][d], e && d==u, false); res %= mod; } if(!e && !z) f[pos][sta] = res; return res;}LL solve(char *str){ int len = strlen(str); for(int i = 0; i < len; ++i){ bit[len-i] = str[i] - '0'; } return dfs(len, 0, 1, 1);}int main(){ int t; scanf("%d", &t); while(t--){ cnt = -1; int root = newNode(); int n; scanf("%d", &n); for(int i = 0; i < n; ++i){ scanf("%s", ch); insert(ch, root); } build_fail(root); init_dp(); memset(f, -1, sizeof(f)); scanf("%s", str); int len = strlen(str); for(int i = len-1; i>=0; --i){ if(str[i]>'0'){ --str[i]; break; } else str[i] = '9'; } LL res = -solve(str); scanf("%s", str); res += solve(str); res = (res + mod) % mod; printf("%lld\n", res); } return 0;}
- 【MZ】ZOJ 3494 BCD Code AC自动机+数位DP
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code 数位DP+AC自动机
- ZOJ 3494 BCD Code (AC自动机+数位DP,5级)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code AC自动机+数位DP
- ZOJ 3494 BCD Code AC自动机+数位DP
- 【ZOJ】3494 BCD Code AC自动机+数位DP
- zoj 3494 BCD Code AC自动机+数位dp
- zoj 3494 BCD Code(AC自动机+数位dp)
- ZOJ 3494 BCD Code AC自动机 + 数位DP
- 【AC自动机+数位DP】【zoj 3494】BCD Code
- ZOJ Problem Set - 3494 BCD Code AC自动机+数位DP
- zoj 3494 BCD Code (ac自动机+数位dp)
- [AC自动机+数位dp] zoj 3494 BCD Code
- ZOJ - 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code (AC自动机 + 数位DP)
- 【学习】linux shell 编程
- 正则表达式语法
- 希尔伯特向量空间中的信号
- windows 绘制窗体时防止闪烁
- IOS中的结构体保存到数组与读取
- 【MZ】ZOJ 3494 BCD Code AC自动机+数位DP
- SQL Server 索引结构及其使用
- PID 在机器人self balance中应用
- 一句话经典总结红黑树插入
- 小流涓涓成江海,拙技点点构平台——多线程开发
- 英文面试自我介绍
- 在 php 中通过 CURL 上传文件
- linux服务器安全加固shell脚本
- Java is Pass-by-Value, Dammit!