P3631 [APIO2011] 方格染色[1]

题目里说把 11 看成红色,00 看成蓝色,那么任意一个 2×22\times 2 的区域,其异或和为 11.

xi,jxi1,jxi,j1xi1,j1=1 x_{i,j}\oplus x_{i-1,j}\oplus x_{i,j-1}\oplus x_{i-1,j-1}=1

接着考虑和这个 2×22\times 2 区域相交了两个格子的区域 [i2,i1]×[j1,j][i-2,i-1]\times[j-1,j],由于异或相消,有

xi,jxi1,jxi,j1xi1,j1=1xi1,jxi2,jxi1,j1xi2,j1=1xi,jxi2,jxi,j1xi2,j1=0 \begin{array}{c|lllll} &x_{i,j}&\oplus \cancel{x_{i-1,j}}&\oplus x_{i,j-1}&\oplus \cancel{x_{i-1,j-1}}&=1\\ \oplus &\cancel{x_{i-1,j}}&\oplus x_{i-2,j}&\oplus \cancel{x_{i-1,j-1}}&\oplus x_{i-2,j-1}&=1\\ \hline &x_{i,j}&\oplus x_{i-2,j}&\oplus x_{i,j-1}&\oplus x_{i-2,j-1}&=0 \end{array}

进一步代入 ii2i'\gets i-2 可以推广到

xi,jxi2k,jxi,j1xi2k,j1=0 x_{i,j}\oplus x_{i-2k,j}\oplus x_{i,j-1} \oplus x_{i-2k,j-1}=0

jj1j'\gets j-1 代入发现

xi,jxi2k,jxi,j1xi2k,j1=0xi,j1xi2k,j1xi,j2xi2k,j2=0xi,jxi2k,jxi,j2xi2k,j2=0 \begin{array}{c|lllll} &x_{i,j}&\oplus x_{i-2k,j}&\oplus \cancel{x_{i,j-1}}&\oplus \cancel{x_{i-2k,j-1}}&=0\\ \oplus&\cancel{x_{i,j-1}}&\oplus \cancel{x_{i-2k,j-1}}&\oplus x_{i,j-2}&\oplus x_{i-2k,j-2}&=0\\ \hline &x_{i,j}&\oplus x_{i-2k,j}&\oplus x_{i,j-2}&\oplus x_{i-2k,j-2}&=0\\ \end{array}

所以可以推广到

xi,jxi2k,jxi,jtxi2k,jt=0 x_{i,j}\oplus x_{i-2k,j}\oplus x_{i,j-t}\oplus x_{i-2k,j-t}=0

同理有

xi,jxi,j2kxit,jxit,j2k=0 x_{i,j}\oplus x_{i,j-2k}\oplus x_{i-t,j}\oplus x_{i-t,j-2k}=0

也就是说

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
constexpr int N = 1e5 + 5;
constexpr int M = 1e9;
using vi = vector<int>;
using constraint = pair<int, int>;

struct ColouredCell {
int x, y, c;
} cc[N];
int n, m, k;
int mapping(int x, int y) {
if (y == 0) return x;
else return y + n;
}
vector<constraint> G[N << 1];
int vis[N << 1], val[N << 1];

int main() {
cin >> n >> m >> k;
for (int i = 1; i <= k; i++) {
cin >> cc[i].x >> cc[i].y >> cc[i].c;
if (cc[i].x % 2 == 1 && cc[i].y % 2 == 1) {
int a = mapping(cc[i].x, 0);
int b = mapping(0, cc[i].y);
G[a].push_back({b, cc[i].c});
G[b].push_back({a, cc[i].c});
} else {
int a = mapping(cc[i].x, 0);
int b = mapping(0, cc[i].y);
G[a].push_back({b, cc[i].c ^ 1});
G[b].push_back({a, cc[i].c ^ 1});
}
}

auto dfs = [&](auto &&F, int u) -> bool {
vis[u] = 1;
// cerr << u << " ";
for (auto [v, cons] : G[u]) {
if (vis[v]) {
if ((val[v] ^ val[u]) != cons) return false;
continue;
}
val[v] = val[u] ^ cons;
if (!F(F, v)) return false;
}
return true;
};

int cnt = -2;
for (int i = 0; i <= n + m; i++) {
if (vis[i]) continue;
cnt++;
if (!dfs(dfs, i)) {
cout << 0 << '\n';
return 0;
}
// cerr << "\n";
}

int b = 2, p = cnt;
int res = 1;
while (p) {
if (p & 1) res = 1ll * res * b % M;
b = 1ll * b * b % M;
p >>= 1;
}
cout << res << '\n';
}

  1. LuoGu Blog ↩︎