问题
给定一个数组 \(A = [a_1, a_2,...a_n]\) ,其中 \(a_i ≤ 2d\) ,在 A 中选择元素的某个子集,并将它们 XOR。求你能得到的不同元素的个数。
思路
显然可以得到一个效率非常劣的做法
x[0].insert(0);
for (int i = 1; i <= n; i++) {
x[i] = x[i - 1];
for (auto cur : x[i - 1]) {
x[i].insert(cur ^ a[i - 1]);
}
}
cout << x[n].size();
我们可以研究一下集合的性质,我们假设 \(a, b\) 为集合中的两个元素,那么 \(a \oplus b\) 也必然在集合中,现在我们回头来考虑一下 \(x_i\) 与 \(a_{i + 1}\) 计算 \(x_{i + 1}\) 的过程 \(:\) 如果 \(a_{i + 1} \in x_i\)那么不用考虑 \(a_{i + 1}\) 的影响,如果没有,那么集合大小铁定会翻两倍,那么这个集合最多大小翻 \(d\) 倍,由此我们可以得到一个时间复杂度为 \(O(n + 2^d)\) 的代码
如果 \(2^d\) 很大,这种算法也会超时