「SCOI2016」围棋

打CF后困不拉基的,搞了一上午...

考虑直接状压棋子,然后发现会t

考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串

于是状态可以\(2^m\)压住了,但还是会T

考虑到复杂度瓶颈在于每行的状态都要枚举上一行的状态,是按行转移的。

那么如果做一个轮廓线,就可以按格子转移

考虑有那些状态,当前格子\(i,j\),当前轮廓线是否可以匹配第一行的串的状态\(s\)

然后你试试发现如果想好好转移

得存一个\((i,j)\)匹配到第一行串的位置\(x\),和第二行串的位置\(y\)

这里的思考方向倾向于先想转移,转移不了再加状态

然后发现这个匹配的过程可以使用KMP优化,转移的均摊是\(O(1)\)的

复杂度\(O(nm2^{m-c+1}c^2)\)

这里复杂度写成\(2^m\)可能不太稳...


Code:

#include <cstdio>
#include <cctype>
#include <cstring>
template <class T>
void read(T &x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
const int mod=1e9+7;
void add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
void mul(int &x,int y){x=1ll*x*y%mod;}
int n,m,c,q,dp[2][1<<12][7][7];
int nxt1[12],nxt2[12],d1[12],d2[12];
char s1[12],s2[12];
void init(char *s,int *d,int *nxt)
{
for(int i=1;i<=c;i++) d[i]=(s[i]=='W'?2:(s[i]=='B'));
for(int j=0,i=2;i<=c;i++)
{
while(j&&d[j+1]!=d[i]) j=nxt[j];
if(d[j+1]==d[i]) ++j;
nxt[i]=j;
}
}
int get(int *nxt,int p,int col,int *d)
{
while(p&&d[p+1]!=col) p=nxt[p];
if(d[p+1]==col) ++p;
return p;
}
int main()
{
read(n),read(m),read(c),read(q);
while(q--)
{
memset(d1,-1,sizeof d1),memset(nxt1,0,sizeof nxt1);
memset(d2,-1,sizeof d2),memset(nxt2,0,sizeof nxt2);
scanf("%s",s1+1),init(s1,d1,nxt1);
scanf("%s",s2+1),init(s2,d2,nxt2);
memset(dp,0,sizeof dp);
int sum=1,cur=0,tx,ty,t,l=m-c+1;
dp[cur][0][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
memset(dp[cur^1],0,sizeof dp[cur^1]);
for(int s=0;s<1<<l;s++)
for(int x=0;x<=c;x++)
for(int y=0;y<=c;y++)
if(dp[cur][s][x][y])
for(int col=0;col<3;col++)
{
tx=get(nxt1,x,col,d1);
ty=get(nxt2,y,col,d2);
if(j+1>=c)
{
t=s&(~(1<<j+1-c));
t|=(tx==c)<<j+1-c;
}
else t=s;
if(j+1>=c&&(s>>j+1-c&1)&&ty==c) continue;
add(dp[cur^1][t][tx][ty],dp[cur][s][x][y]);
}
cur^=1;
mul(sum,3);
}
for(int s=0;s<1<<l;s++)
for(int x=0;x<=c;x++)
for(int y=0;y<=c;y++)
if(x||y)
add(dp[cur][s][0][0],dp[cur][s][x][y]),dp[cur][s][x][y]=0;
}
int ans=0;
for(int s=0;s<1<<l;s++)
add(ans,dp[cur][s][0][0]);
add(sum,mod-ans);
printf("%d\n",sum);
}
return 0;
}

2019.3.6

「SCOI2016」围棋 解题报告的更多相关文章

  1. 「SCOI2016」妖怪 解题报告

    「SCOI2016」妖怪 玄妙...盲猜一个结论,然后过了,事后一证,然后假了,数据真水 首先要最小化 \[ \max_{i=1}^n (1+k)x_i+(1+\frac{1}{k})y_i \] \ ...

  2. 「SCOI2016」美味 解题报告

    「SCOI2016」美味 状态极差无比,一个锤子题目而已 考虑每次对\(b\)和\(d\)求\(c=d \ xor \ (a+b)\)的最大值,因为异或每一位是独立的,所以我们可以尝试按位贪心. 如果 ...

  3. 「SCOI2016」萌萌哒 解题报告

    「SCOI2016」萌萌哒 这思路厉害啊.. 容易发现有个暴力是并查集 然后我想了半天线段树优化无果 然后正解是倍增优化并查集 有这个思路就简单了,就是开一个并查集代表每个开头\(i\)每个长\(2^ ...

  4. 「ZJOI2016」旅行者 解题报告

    「ZJOI2016」旅行者 对网格图进行分治. 每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分 至于复杂度么,我不会阿 Code: #incl ...

  5. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  6. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  7. 「HNOI2016」网络 解题报告

    「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...

  8. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  9. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

随机推荐

  1. HDU 3947 Assign the task

    http://acm.hdu.edu.cn/showproblem.php?pid=3974 Problem Description There is a company that has N emp ...

  2. C语言操作WINDOWS系统存储区数字证书相关函数详解及实例

     C语言操作WINDOWS系统存储区数字证书相关函数详解及实例 以下代码使用C++实现遍历存储区证书及使用UI选择一个证书 --使用CertOpenSystemStore打开证书存储区. --在循环中 ...

  3. [转帖]windows+xshell+xming访问非桌面版Linux服务器

    windows+xshell+xming访问非桌面版Linux服务器 2016年06月05日 00:09:11 jxxiaohou 阅读数:11996 标签: Linux 更多 个人分类: Linux ...

  4. 爱上linux 简单实现移动办公处理环境.

    1. 这周一直在鼓捣linux上面的环境测试. 简单的将 我们的产品部署到了linux上面 详情见前面的 blog 2. 有时候下班了 或者是 在WC (科技园wc排队 说多了都是泪) 或者是眼睛不舒 ...

  5. redis的配置文件解释

    redis的守护进行 守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程.它是一个生存期较长的进程,通常独立 于控制终端并且周期 ...

  6. 替换JDK 对eclipse的影响?

    问题  替换原有的JDK 对 eclipse有影响么? 之前用的eclipse是32位的,我的电脑是64位的,装的JDK是也是32位的,所以不影响使用! 但是,前两天装了一个ideal,新配置了一个9 ...

  7. 一、使用Navicat连接阿里云服务器宝塔面板里创建的数据库

    一.数据库配置连接  (通过新增用户的方式)

  8. HJ212 CRC 16 (C#)

    算法 CRC16 校验寄存器赋值为 0xFFFF: 取被校验串的第一个字节赋值给临时寄存器: 临时寄存器与 CRC16 校验寄存器的高位字节进行"异或"运算,赋值给 CRC16 校 ...

  9. DeepLearning网络设计总结

    检测网络: 1. tiling层可以减少计算量,deconvolution相比tiling性能要好一些

  10. django CBV视图源码分析

    典型FBV视图例子 url路由系统 from django.conf.urls import url from django.contrib import admin from luffycity.v ...