题目 | XOR to All
AtCoder Regular Contest 135
C - XOR to All
https://atcoder.jp/contests/arc135/tasks/arc135_c
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : $500$ points
Problem Statement
You are given a sequence of non-negative integers $A = (A_1, \ldots, A_N)$. You can do the operation below any number of times (possibly zero).
- Choose an integer $x\in \{A_1,\ldots,A_N\}$.
- Replace $A_i$ with $A_i\oplus x$ for every $i$ ($\oplus$ denotes the bitwise $\mathrm{XOR}$ operation).
Find the maximum possible value of $\sum_{i=1}^N A_i$ after your operations.
Constraints
- $1\leq N \leq 3\times 10^{5}$
- $0\leq A_i < 2^{30}$
Input
Input is given from Standard Input from the following format:
$N$
$A_1$ $\ldots$ $A_N$
Output
Print the maximum possible value of $\sum_{i=1}^N A_i$ after your operations.
Sample Input 1
5
1 2 3 4 5
Sample Output 1
19
Here is a sequence of operations that achieves $\sum_{i=1}^N A_i = 19$.
- Initially, the sequence $A$ is $(1,2,3,4,5)$.
- An operation with $x = 1$ changes it to $(0,3,2,5,4)$.
- An operation with $x = 5$ changes it to $(5,6,7,0,1)$, where $\sum_{i=1}^N A_i = 5 + 6 + 7 + 0 + 1 = 19$.
Sample Input 2
5
10 10 10 10 10
Sample Output 2
50
Doing zero operations achieves $\sum_{i=1}^N A_i = 50$.
Sample Input 3
5
3 1 4 1 5
Sample Output 3
18
我的笔记
本题中的 "You can do the operation below any number of times (possibly zero)." 和 "Sample 1" 就是个迷惑人的幌子,说是可以进行任意次异或操作,然而结果等价于只进行一次异或操作,因为:$(A_x\ \mathrm{XOR}\ A_i)\ \mathrm{XOR}\ (A_y\ \mathrm{XOR}\ A_i)=A_x\ \mathrm{XOR}\ A_y$
具体到示例 $1$ 的 $(1,2,3,4,5)$,先用 $1$ 异或得到 $(0,3,2,5,4)$,再用 $5$ 异或得到 $(5,6,7,0,1)$,这俩步其实等价于直接用 $4$ 异或($4$ 是第二步 $5$ 原来对应的那个数)
所以该题简化为:有 $N$ 个数,在其中选 $1$ 个数(可以不选),用这个数与这 $N$ 个数异或,将结果求和,求和的最大值。
然后直接暴力求解一个个异或再求和肯定是不可行的,要整体来操作。
本题异或、求和都可以看成按位操作,所以可以直接统计出每一位 $0$ 和 $1$ 的数量,如果异或的那个数该位为 $0$,那么 $0、1$ 不翻转,如果是 $1$ 那么 $0、1$ 翻转,统计一次需要循环 $30$ 次(因为数字不大于 $2^{30}$)。统计了一位之后就可以把这一位算出来,第一位乘 $2^{0}$,第二位乘 $2^{1}$,第三位乘 $2^{2}$,$\dots$,第三十位乘 $2^{29}$,这样就只花了 $30$ 次循环就求出了一次和。总共有 $N$ 个数字,用每个数字都试一遍,然后找到最大值即可,时间复杂度 $O(30\times N)$ ,$1\leq N \leq 3\times 10^{5}$,因此可以 AC.
代码
#include <bits/stdc++.h>
using namespace std;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int N;
cin >> N;
vector<int> A(N);
vector<int> bit(30);
for (int i = 0; i < N; i++)
{
cin >> A[i];
int t = A[i];
for (int i = 0; t; i++, t >>= 1)
{
bit[i] += t & 1;
}
}
long long sum = accumulate(A.begin(), A.end(), 0LL);
for (int i = 0; i < N; i++)
{
long long cur_sum = 0, d = 1;
int t = A[i], bit_sum;
for (int j = 0; j < 30; j++)
{
if (t & 1)
{
bit_sum = N - bit[j];
}
else
{
bit_sum = bit[j];
}
t >>= 1;
cur_sum += d * bit_sum;
d <<= 1;
}
sum = max(sum, cur_sum);
}
cout << sum << endl;
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi