D

我们直接枚举 3n3^n 个 mask (i.e., 0,1,?0,1,\texttt{?})

考虑 mask 的第 nn 位,如果是 0,10,1,那么剩下的其实就是大小为 n1n-1 的一个子问题;比较麻烦的是当这一位取 ?\texttt{?} 的时候。

我们让子问题的解为 S=umap[M,A],M[0,3n1)S=\texttt{umap}[M,A], M\in [0, 3^{n-1}),其中的 AA 表示 mask MM 可以匹配的 aia_{i} 之和,我们既然可以知道第 nn 位分别是 0,10,1 时的解,那么根据

?M=1M+0M\texttt{?}M=\texttt{1}M+\texttt{0}M

我们就可以计算当前位取 ??,其余 n1n-1 位为 MM 时候的解为 S?[M]=S1[M]+S0[M]S_{?}[M]=S_{1}[M]+S_{0}[M]

时间复杂度 O(3n)O(3^n)

Problem D
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
#include <cassert>
#include <cmath>
#include <iostream>
#include <vector>

constexpr int M = 43046721;

int main() {
int n;
std::cin >> n;
std::vector<int> a(1 << n);
for (auto &x : a)
std::cin >> x;

int ans = 0;
auto F = [&](auto f, int p, int prefix) -> std::vector<int> {
if (p == 0) {
ans ^= a[prefix];
return {a[prefix]};
}

// suppose 1 on this bit
auto l = f(f, p - 1, prefix << 1 | 1);
// suppose 0 on this bit
auto r = f(f, p - 1, prefix << 1);

assert(l.size() == r.size());
assert(l.size() == std::pow(3, p - 1));

int sum = 0;
std::vector<int> ret;
for (int i = 0; i < l.size(); i++) {
ans ^= l[i] + r[i];
ret.push_back(l[i] + r[i]);
}
for (auto i : l)
ret.push_back(i), sum += i;
for (auto i : r)
ret.push_back(i), sum += i;

return ret;
};

F(F, n, 0);
std::cout << ans << "\n";
}