题意:对于集合 S = { a 1 , a 2 , … , a n } S = \set{a_1, a_2, \dots, a_n} S={a1,a2,…,an} ,设 X ( S ) = a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n X(S) = a_1 \oplus a_2 \oplus \dots \oplus a_n X(S)=a1⊕a2⊕⋯⊕an( ⊕ \oplus ⊕ 表示异或)。给定 S = { a 1 , a 2 , … , a n } S = \set{a_1, a_2, \dots, a_n} S={a1,a2,…,an} ,求 max T ⊆ S X ( T ) \max_{T \subseteq S} X(T) maxT⊆SX(T) 。
因为 a i < 2 60 a_i < 2^{60} ai<260 ,所以设 a i a_i ai 的二进制形式为 b i , 59 b i , 58 … b i , 1 b i , 0 ‾ \overline{b_{i, 59}b_{i, 58} \dots b_{i, 1}b_{i, 0}} bi,59bi,58…bi,1bi,0 ,设 c k c_k ck 表示满足 b i , k = 1 b_{i, k} = 1 bi,k=1 的 i i i 的个数。如果 c k c_k ck 是奇数,则 X ( S ) X(S) X(S) 一定包含 2 k 2^k 2k 位。
因为一个数异或自身等于零,所以我们可以允许每个数使用多次,进而可知,用 a i ⊕ a j a_i \oplus a_j ai⊕aj 替换 a j a_j aj( a i a_i ai 不变)对结果也没有影响,也不会影响 b b b 中 1 1 1 的个数的奇偶性,我们称这种替换为“合法替换”。而且,对 S S S 的任意子集 T T T ,都可以对 S S S 进行若干次“合法操作”得到 S ′ S' S′ ,使得 X ( S ′ ) = X ( T ) X(S') = X(T) X(S′)=X(T) 。
设命题 p k p_k pk 为真当且仅当 ∃ i , b i , k = 1 ∧ ∀ l > k , b i , l = 0 \exists i, b_{i, k} = 1 \land \forall l > k, b_{i, l} = 0 ∃i,bi,k=1∧∀l>k,bi,l=0 。我们可以借助类似高斯消元的方法对 S S S 中的元素进行若干次“合法替换”,使得 S S S(严谨表示应该用 S ′ S' S′ ,但为了方便仍使用 S S S )满足:
- ∀ k , p k → c k = 1 \forall k, p_k \to c_k = 1 ∀k,pk→ck=1
- 如果 p k p_k pk 为假,则无法通过若干次“合法替换”使 p k p_k pk 为真。
- 如果 c k c_k ck 为偶数,那么如果经过若干次“合法替换”使 c k c_k ck 为奇数,则必然存在 l > k l > k l>k 使得 c l c_l cl 从奇数变为偶数。
此时, X ( S ) X(S) X(S) 就是所求的最大值,因为如果继续“合法替换”,即使将 c k c_k ck 从偶数变为奇数,也一定会牺牲更高位,得不偿失。
代码:
#define NDEBUG
#include <bits/stdc++.h>
using ll = long long;
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<ll> a(n);
for (ll &i : a)
cin >> i;
for (int row{}, col{59}, pivot; col >= 0; --col)
{
for (pivot = row; pivot < n && ~a[pivot] >> col & 1; ++pivot)
;
if (pivot < n)
{
swap(a[row], a[pivot]);
for (int i{}; i < n; ++i)
if (i != row && a[i] >> col & 1)
a[i] ^= a[row];
++row;
}
}
ll ans{};
for (ll &i : a)
ans ^= i;
cout << ans;
return 0;
}