题意:

$n*m:n,m \le 10^6$的网格,每个$2 \times 2$的方格必须有1个或3个涂成红色,其余涂成蓝色

有一些方格已经有颜色

求方案数


太神了!!!花我三节课

首先想了一下只有两行,发现可以直接$f[i][3]\ DP$出来,每一列放的方案只与上一列有关

如果有多行呢,我们可以把上一列放的状态状压$f[i][s]$,然后枚举转移

复杂度爆炸

好,看一眼题解

woc题解说的些什么东西根本看不懂,还是自己想吧

发现,貌似一个状态只有两个后继状态唉,就是说这一列的右面一列只有两种放法是合法的

数学归纳法证一下,两行的情况每种列的放法有两个后继,设n行成立,那么n+1行的下一列选或不选就已经确定了...好像成立唉!

并且这两个后继还是每个位置都相反的!

总算看明白题解那句:

如果确定了第一行,接下来的每一行只会是 1.上一行所有奇数列异或1后得到 2.上一行所有偶数列异或1后得到 (这里把之前的行列倒换了)

其实可以直观理解,因为要保证是奇性啊

这样的话,不考虑已经涂色的,方案数就是第一行的方案数*(行数-1)$2^{n+m-1}$了

考虑涂色!

首先,每个有涂色的行两个后继状态只有一个合法了

再考虑这一行的涂色对第一行的影响,如果有一行两个位置$x,y$已经涂色,因为只有那两种变换所以:

$1.\ x,y同奇偶,每行都必须同色$

$2.\ x,y异奇偶,跟这一行同奇偶的行必须同色,异奇偶的行必须异色$

用个种类并查集就可以判断无解了!

方案数?把有关系限制的列连起来,求连通块数就行了

注意第一行如果有已经涂色的,颜色就直接确定了而不是同色或者异色,所以包含他们的连通块不能再考虑

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define pii pair<int, int>
#define MP make_pair
#define fir first
#define sec second
const int N=1e6+, P=1e9;
typedef long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int n, m, k, c[N], p, x, y;
struct meow{int r, c;}t;
vector<meow> q[N];
int fa[N];
int find(int x) {return x==fa[x] ? x : fa[x]=find(fa[x]);}
struct UFS{
int fa[N], val[N];
int find(int x) {
if(x == fa[x]) return x;
int root = find(fa[x]);
val[x] ^= val[fa[x]];
return fa[x] = root;
}
bool Union(int x, int y, int p) {
int f1 = find(x), f2 = find(y);
if(f1 != f2) {
fa[f1] = f2;
val[f1] = val[x]^val[y]^p;
} else if((val[x]^val[y]) != p) return false;
return true;
}
}F;
int fix[N], mark[N];
int Pow(ll a, int b) {
ll ans=;
for(; b; b>>=, a=a*a%P)
if(b&) ans=ans*a%P;
return ans;
}
int main() {
freopen("in","r",stdin);
n=read(); m=read(); k=read();
for(int i=; i<=k; i++) {
x=read(), t.r=read(), t.c=read(), q[x].push_back(t);
mark[x] = ;
if(x == ) fix[t.r] = ;
}
for(int i=; i<=m; i++) fa[i] = F.fa[i] = i;
for(int i=; i<=n; i++)
for(int j=; j<(int)q[i].size(); j++) {
int a = q[i][j-].c, b = q[i][j].c, x=q[i][j-].r, y=q[i][j].r;
int f1 = find(x), f2 = find(y);
fa[f1] = f2;
if(fix[f1]) fix[f2] = ;
int p = a^b; if((x&) != (y&)) p ^= (i-)&;
if(!F.Union(x, y, p)) {puts(""); return ;}
}
int ans = ;
for(int i=; i<=n; i++) ans += !mark[i];
for(int i=; i<=m; i++) if(fa[i]==i && !fix[i]) ans++;
printf("%d\n", Pow(, ans));
}

BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]的更多相关文章

  1. bzoj 2303: [Apio2011]方格染色【并查集】

    画图可知,每一行的状态转移到下一行只有两种:奇数列不变,偶数列^1:偶数列不变,奇数列^1 所以同一行相邻的变革染色格子要放到同一个并查集里,表示这个联通块里的列是联动的 最后统计下联通块数(不包括第 ...

  2. bzoj 2303: [Apio2011]方格染色

    传送门 Description Sam和他的妹妹Sara有一个包含n × m个方格的表格.她们想要将其的每个方格都染成红色或蓝色.出于个人喜好,他们想要表格中每个2 × 2的方形区域都包含奇数个(1 ...

  3. BZOJ 2303: [Apio2011]方格染色 题解

    题目大意: 有n*m的方格,中间的数要么是1,要么是0,要求任意2*2的方格中的数异或和为1.已知一部分格子中的数,求合法的填数的方案数. 思路: 由题意得:a[i][j]^a[i][j+1]^a[i ...

  4. BZOJ2303 [Apio2011]方格染色 并查集

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2303 题意概括 现在有一个N*M矩阵,矩阵上只能填数字0或1 现在矩阵里已经有一些格子被填写了数字 ...

  5. BZOJ_2303_[Apio2011]方格染色 _并查集

    BZOJ_2303_[Apio2011]方格染色 _并查集 Description Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好, ...

  6. [BZOJ2303][Apio2011]方格染色

    [BZOJ2303][Apio2011]方格染色 试题描述 Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好,他们想要表格中每个2 × ...

  7. BZOJ.2054.疯狂的馒头(并查集)

    BZOJ 倒序处理,就是并查集傻题了.. 并查集就是确定下一个未染色位置的,直接跳到那个位置染.然而我越想越麻烦=-= 以为有线性的做法,发现还是要并查集.. 数据随机线段树也能过去. //18400 ...

  8. 2021.08.03 BZOJ 疯狂的馒头(并查集)

    2021.08.03 BZOJ 疯狂的馒头(并查集) 疯狂的馒头 - 题目 - 黑暗爆炸OJ (darkbzoj.tk) 重点: 1.并查集的神奇运用 2.离线化 题意: 给一个长为n的序列,进行m次 ...

  9. BZOJ2303: [Apio2011]方格染色 【并查集】

    Description Sam和他的妹妹Sara有一个包含n × m个方格的表格.她们想要将其的每个方格都染成红色或蓝色.出于个人喜好,他们想要表格中每个2 × 2的方形区域都包含奇数个(1 个或 3 ...

随机推荐

  1. poj_3281Dining(网络流+拆点)

    poj_3281Dining(网络流+拆点) 标签: 网络流 题目链接 题意: 一头牛只吃特定的几种食物和特定的几种饮料,John手里每种食物和饮料都只有一个,问最多能够满足几头牛的需求(水和食物都必 ...

  2. hdu_1711Number Sequence(kmp)

    Number Sequence Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. django入门基础

    首先要说的是django与其他的框架不同,django是一个封装的及其完善的框架,我们使用django也不会像之前写学生系统那样,django操作数据库使用自带的ORM来进行操作,Torando与Fl ...

  4. NYOJ 1248 海岛争霸(Dijkstra变形——最短路径最大权值)

    题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=1248 描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比 ...

  5. github设置添加SSH

    很多朋友在用github管理项目的时候,都是直接使用https url克隆到本地,当然也有有些人使用 SSH url 克隆到本地.然而,为什么绝大多数人会使用https url克隆呢? 这是因为,使用 ...

  6. Python3 的数据类型

    Python3 的数据类型 整形,浮点型,布尔类型 类型转换 int() 整形 采用截断的方式即向下取整,比如 a=5.5 int (a) 返回值为5 怎样才能使int()按照"四舍五入&q ...

  7. Angular CLI: 发布到 GitHub Pages

    发布 Angular 应用的简单方式是使用 GitHub Pages. 首先需要创建一个 GitHub 账号,随后,为您的项目创建一个仓库.记下 GitHub 中的用户名和项目名称. 例如,我的 Gi ...

  8. CCF系列之矩阵(201512-5)

    试题名称: 矩阵 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 创造一个世界只需要定义一个初状态和状态转移规则. 宏观世界的物体运动规律始终跟物体当前的状态有关,也就是说只要 ...

  9. ajax和跨域

    一.简介 ajax是什么? AJAX(Asynchronous JavaScript and XML) 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. AJAX, (异步的JavaSc ...

  10. java注解--Annotation

    Annotation(注释) 概述 从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是 Annotation(注释) Annotation 其实就是代码里的特殊 ...