ZOJ 3494 BCD Code AC自动机+数位DP
来源:互联网 发布:淘宝女包店铺 编辑:程序博客网 时间:2024/04/28 12:58
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;}
0 0
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code 数位DP+AC自动机
- ZOJ 3494 BCD Code (AC自动机+数位DP,5级)
- 【MZ】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)
- 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)
- hdu 2243 AC自动机 + 矩阵加速
- OpenGL: 阴影算法
- 发现大牛博客,特别兴奋!
- 在应用间利用KeyChain共享数据
- JAVA的Date类与Calendar类
- ZOJ 3494 BCD Code AC自动机+数位DP
- ORACLE OLTP&OLAP
- 实现复数类中的运算符重载
- 用AVOS Cloud加速移动开发,map.save()即可把键值对保存到服务器上
- dp
- HDU 1022 Train Problem I(栈的应用)
- 斐波那契查找-类似于二分查找
- RHEL5下安装vim编辑器
- UDP的connect