【BZOJ 4572】【SCOI 2016】围棋
http://www.lydsy.com/JudgeOnline/problem.php?id=4572
轮廓线DP:设\(f(i,j,S,x,y)\)。
\(S\)表示\((i,1)\)到\((i,j)\)和\((i-1,j+1)\)到\((i-1,m)\)的长度为m的轮廓线上与每个位置作为末位是否与第一个串匹配的状态。
\(x,y\)分别表示\((i,j)\)这个位置作为末位与第一/二个串kmp到了哪个位置。
\(x,y\)取值范围是\([0,c)\),因为当\(x,y\)其一取到c时,这个状态主要考虑对下一个位置上状态的贡献,所以会沿着失配指针往前跳一个继续匹配,不如把\(x/y=c\)的状态和\(x/y=fail[c]\)的状态压在一起。
注意有的连通性状压轮廓线长度为m+1,这个不关心8联通,所以长度为m。
又因为\(S\)的前\(c-1\)位一定是0,可以不记录这几位,所以S的长度是\(m-c+1\)。
时间复杂度\(O(nm2^{m-c+1}c^2)\)。
注意滚动数组一定要全部清空!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mo = 1000000007;
int n, m, c, q, r1[10], r2[10], fail1[10], fail2[10];
int f[1 << 12][6][6], g[1 << 12][6][6], t1[10][10], t2[10][10];
char c1[10], c2[10];
int change(int S, int tmp, int mark) {
if (tmp < 0) return S;
return S ^ ((mark ^ ((S >> tmp) & 1)) << tmp);
}
int ipow(int a, int b) {
int ret = 1, w = a;
while (b) {
if (b & 1) ret = 1ll * ret * w % mo;
w = 1ll * w * w % mo;
b >>= 1;
}
return ret;
}
int main() {
scanf("%d%d%d%d", &n, &m, &c, &q);
int ans_tot = ipow(3, n * m);
while (q--) {
scanf("%s%s", c1 + 1, c2 + 1);
for (int i = 1; i <= c; ++i) {if (c1[i] == 'W') r1[i] = 1; if (c1[i] == 'B') r1[i] = 2; if (c1[i] == 'X') r1[i] = 0;}
for (int i = 1; i <= c; ++i) {if (c2[i] == 'W') r2[i] = 1; if (c2[i] == 'B') r2[i] = 2; if (c2[i] == 'X') r2[i] = 0;}
int p = 0;
for (int i = 2; i <= c; ++i) {
while (p && r1[p + 1] != r1[i]) p = fail1[p];
fail1[i] = r1[p + 1] == r1[i] ? ++p : 0;
}
p = 0;
for (int i = 2; i <= c; ++i) {
while (p && r2[p + 1] != r2[i]) p = fail2[p];
fail2[i] = r2[p + 1] == r2[i] ? ++p : 0;
}
for (int i = 0; i < c; ++i)
for (int j = 0; j <= 2; ++j) {
p = i; while (p && r1[p + 1] != j) p = fail1[p];
t1[i][j] = r1[p + 1] == j ? p + 1 : 0;
p = i; while (p && r2[p + 1] != j) p = fail2[p];
t2[i][j] = r2[p + 1] == j ? p + 1 : 0;
}
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
g[0][0][0] = 1;
int bas = (1 << (m - c + 1)) - 1, newx, newy, T;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (j != 1) memcpy(f, g, sizeof(f));
else {
memset(f, 0, sizeof(f));
for (int S = 0; S <= bas; ++S)
for (int x = 0; x < c; ++x)
for (int y = 0; y < c; ++y)
if (g[S][x][y])
(f[S][0][0] += g[S][x][y]) %= mo;
}
memset(g, 0, sizeof(g));
for (int S = 0; S <= bas; ++S)
for (int x = 0; x < c; ++x)
for (int y = 0; y < c; ++y)
if (f[S][x][y])
for (int now = 0; now <= 2; ++now) {
newx = t1[x][now]; newy = t2[y][now];
if (newy == c && j - c >= 0 && ((S >> (j - c)) & 1)) continue;
if (newx == c) T = change(S, j - c, 1);
else T = change(S, j - c, 0);
if (newx == c) newx = fail1[c];
if (newy == c) newy = fail2[c];
(g[T][newx][newy] += f[S][x][y]) %= mo;
}
}
}
int ans = ans_tot;
for (int S = 0; S <= bas; ++S)
for (int x = 0; x < c; ++x)
for (int y = 0; y < c; ++y)
((ans -= g[S][x][y]) += mo) %= mo;
printf("%d\n", ans);
}
}
【BZOJ 4572】【SCOI 2016】围棋的更多相关文章
- bzoj 4568 [SCOI 2016] 幸运数字
题目大意 给定一棵\(n\)个点的树,每个点有权值 \(q\)次询问树上路径中 每个点权值可选可不选的最大异或和 \(n\le 2*10^4,q\le 2*10^5,val[i]\le 2^{60}\ ...
- [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分
[LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分 题意 给定一个字符串 \(S\), 求有多少种将 \(S\) 的子串拆分为形如 AABB 的拆分方案 \(| ...
- [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)
[BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...
- SCOI 2016 萌萌哒
SCOI 2016 萌萌哒 solution 有点线段树的味道,但是并不是用线段树来做,而是用到另外一个区间修改和查询的利器--ST表 我们可以将一个点拆成\(logN\)个点,分别代表从点\(i\) ...
- 【BZOJ 4568】【SCOI 2016】幸运数字
写了一天啊,调了好久,对拍了无数次都拍不出错来(数据生成器太弱了没办法啊). 错误1:把线性基存成结构体,并作为函数计算,最后赋值给调用函数的变量时无疑加大了计算量导致TLE 错误2:像这种函数(A, ...
- BZOJ.4572.[SCOI2016]围棋(轮廓线DP)
BZOJ 洛谷 \(Description\) 给定\(n,m,c\).\(Q\)次询问,每次询问给定\(2*c\)的模板串,求它在多少个\(n*m\)的棋盘中出现过.棋盘的每个格子有三种状态. \( ...
- 【BZOJ 4569】【SCOI 2016】萌萌哒
http://www.lydsy.com/JudgeOnline/problem.php?id=4569 用ST表表示所有区间,根据ST表中表示的区间长度种一棵nlogn的树,类似线段树,每个节点的左 ...
- 【BZOJ 4571】【SCOI 2016】美味
http://www.lydsy.com/JudgeOnline/problem.php?id=4571 这道题因为有加法,不能像可持久化trie那样每次判断只判断一个子树,而是在主席树上查询\(\l ...
- 【BZOJ 4570】【SCOI 2016】妖怪
http://www.lydsy.com/JudgeOnline/problem.php?id=4570 对于每个妖怪的两个值,看成二位平面上的一个点的横纵坐标(x,y). 因为只关心a/b,所以设经 ...
随机推荐
- 【Luogu】P3930 SAC E#1 - 一道大水题 Knight
[题目]洛谷10月月赛R1 提高组 [题意]给定n*n棋盘和<=16个棋子,给几个棋子种类和攻击范围,现我方只有一马,求能否吃王. [算法]状压+BFS [题解]16种棋子中,马不能吃马,直接处 ...
- 用vue快速开发app的脚手架工具
前言 多页面应用于结构较于简单的页面,因为简答的页面使用router又过于麻烦.本脚手架出于这样的场景被开发出来. 使用脚手架搭配Hbuilder也同样可以快速使用vue开发安卓和IOS APP. 本 ...
- centos 挂载数据盘
第一.检查硬盘设备是否有数据盘 fdisk -l 第二.数据硬盘分区 fdisk /dev/vdb 第三.ext3格式化分区 mkfs.ext3 /dev/vdb1 第四.挂载新分区 A - 新建目录 ...
- 广度优先算法(BFS)与深度优先算法(DFS)
一.广度优先算法BFS(Breadth First Search) 基本实现思想 (1)顶点v入队列. (2)当队列非空时则继续执行,否则算法结束. (3)出队列取得队头顶点v: (4)查找顶点v的所 ...
- FineReport——巧妙实现类tab布局
在FR中,表达form支持局部刷新和tab布局,在报表中,不能做到这样,只能舍弃一些功能来做到类似的tab布局. 首先,在参数面板放一个文本控件temp,用作一个临时值,需要设置一个默认值,而切换是通 ...
- FineReport——登录不到决策系统
在不断的测试过程中,可能会造成缓存数据的累积,所以在登录过程中可能会出现登录不到决策系统,而是跳转到某一模板页面 解决方法就是清理缓存或者换一个浏览器测试.
- webIcon
webIcon是我在拿别人的模板参考的时候我发现的一个东西,觉得挺不错的一个东西,但是后来发现用webIcon其实我也不知道是好还是不好,因为要用到字体,字体文件其实挺大的,所以当你要的图标不多的时候 ...
- windows7配置python和django的开发环境
直接上图,这是我在我的电脑配置windows7python和django开发环境的所有用到的软件 要求不高,只需要这几个软件的版本相一致就行, 需要注意的是软件安装时需要统一是32位或者64位的软件, ...
- .vue,跟小程序文件在sublime里面怎么实现代码格式化
.vue文件跟小程序的.wxml,.wxss用sublime的HTML/CSS/JS prettify插件也可以实现格式化代码的效果 首先你在sublime要已经安装好了HTML/CSS/JS pre ...
- Mayavi入门
环境,win7/10 64位, python3.x 1,安装 Mayavi4.6 原装的pip下载奇慢,先更换一下源,豆瓣的更新要比清华的快 首先在window的文件夹窗口输入 : %APPDATA% ...