B. Dima and a Bad XOR
題解
有個重要的觀察,就是 xor 後的數值一定會落在 $[0, 1024)$ 之間!
DP
對於每一個 row $r_i$,對於 $[0, 1024)$ 每個數值,如果我們可以利用 $r_0$ 到 $r_{i-1}$ xor 出來的話,我們記錄下我們的選擇。
Enumeration
對於每一個 row 我們都選第一個數字來 xor。如果結果不是 0,就得到解了; 如果結果是零,我們在任何一個 row 可以找一個與該 row 第一個數字不同的數字來替換的話,也得解,否則無解。
替換可以 work 的原因是:已知 $x_0\ xor\ x_1\ xor\ …\ x_n = 0$,你拿任一個 $x_i$ 出來,用一個不同的數字去換,必可以得到 $\neq 0$ 的結果。
AC Code
Using DP
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
|
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m;
scanf("%d %d", &n, &m);
// 500 * 500 * 1024 = 25 * 10^7 = 2.5 * 10^8
vector<int> ans[1024];
for (int i = 0; i < n; i++) {
vector<int> newAns[1024];
for (int j = 0; j < m; j++) {
int num;
scanf("%d", &num);
if (i == 0) {
if (newAns[num].size() == 0)
newAns[num].push_back(j);
} else {
for (int k = 0; k < 1024; k++) {
if (ans[k].size() > 0 && newAns[num ^ k].size() == 0) {
// this optimization is a must
// vector is slow
vector<int> tmp(ans[k]);
tmp.push_back(j);
newAns[num ^ k] = tmp;
}
}
}
}
for (int j = 0; j < 1024; j++)
ans[j] = newAns[j];
}
for (int i = 1; i < 1024; i++) {
if (ans[i].size() > 0) {
// print ans
printf("TAK\n");
for (auto j : ans[i])
printf("%d ", j + 1);
return 0;
}
}
printf("NIE\n");
return 0;
}
|
Using enumeration + observation
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
|
int main()
{
int n, m;
scanf("%d %d", &n, &m);
int ans = 0;
int selection[n] = {0};
int inp[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &inp[i][j]);
}
ans ^= inp[i][0];
}
if (ans == 0) {
for (int i = 0; i < n; i++) {
for (int j = 1; j < m; j++) {
// find diff
if (inp[i][j] != inp[i][0]) {
selection[i] = j;
ans ^= inp[i][0];
ans ^= inp[i][j];
goto done;
}
}
continue;
done:
break;
}
}
if (ans != 0) {
printf("TAK\n");
for (int i = 0; i < n; i++)
printf("%d ", selection[i] + 1);
} else {
printf("NIE\n");
}
}
|