解析
这个问题可以用卷积法来解决。
由于 A 经过 N 次运算成为原始状态,因此只需考虑 j 次运算使得 0\leq j\leq N-1 经过 j 次运算后,值 \displaystyle\sum_{i=0}^{N-1} (A_i|B_i) 由原来的给定序列 A 和 B(运算前)表示为 \displaystyle\sum_{i=0}^{N-1} (A_{(i+j)\% N}|B_i),因此只需找出 0\leq j\leq N-1 内的最大值即可。
现在,我们来计算 0\leq j\leq N-1 的最大值。在约束条件下,0\leq A_i,B_i\leq 31,但逻辑和可以按位计算(因为它不会导致进位),所以只需考虑 0\leq A_i,B_i\leq 1;然后,我们可以独立考虑 2^0 s、 2^1 s、 2^2 s、 2^3 s 和 2^4 s 的位置。也就是说,值等于
\displaystyle\sum_{i=0}^{N-1} (A_{(i+j)\% N}|B_i) =\displaystyle\sum_{k=0}^{4}2^k\cdot\left(\displaystyle\sum_{i=0}^{N-1} (A_{(i+j)\% N,k}|B_{i,k})\right),
其中 A_{i,k} 和 B_{i,k} 是 A_i 和 B_i 的 k 个最小有效位。
对于 a=(a_0,a_1,\ldots,a_{N-1}) 和 b=(b_0,b_1,\ldots,b_{N-1}) 来说对于 (0\leq a_i,b_i\leq 1),我们如何用卷积法求得 \displaystyle\sum_{i=0}^{N-1} (a_{(i+j)\% N}|b_{i})?
首先,(为了求出作为卷积的这对索引的和,)设 a'=(a'_{0},a'_{1},\ldots, a'_{2N-1})=(a_{0},a_{1},\ldots,a_{N-1},a_{0},a_{1},\ldots,a_{N-1} ) 是两份 a 的并集,b'=(b'_{0},b'_{1},\ldots, b'_{N-1})=(b_{N-1},b_{N-2},\ldots,b_{0}) 是 b 的反向,c'=a'*b'=(c'_0,c'_1,\ldots, c'_{3N-1}) 是它们的卷积;那么
c'_{N-1+j}=\displaystyle\sum_{i=0}^{N-1} a'_{i+j}\cdot b'_{N-1-i}=\displaystyle\sum_{i=0}^{N-1} a_{(i+j)\% N}\cdot b_i .
这里,对于 0\leq x,y\leq 1,如果 x=y=1 为 x\cdot y,则 x\cdot y=1 为 x=y=1,否则 x\cdot y=0 为 x=y=1,所以 x\cdot y=x\& y 为 x\cdot y=x\& y(其中 \& 为逻辑积(AND 运算))。此外,\overline{(x|y)}=\bar{x}\&\bar{y} 成立,其中 \bar{x} 是 x 的否定,所以 \bar{a'}=(\bar{a}'_{0},\bar{a}'_{1},\ldots, \bar{a}'_{2N-1}) 和 \bar{b'}=(\bar{b}'_{0},\bar{b}'_{1},\ldots, \bar{b}'_{N-1}) 的卷积得
(\bar{a'}*\bar{b'})_{N-1+j} =\displaystyle\sum_{i=0}^{N-1} \bar{a}_{(i+j)\% N}\cdot \bar{b}_i =\displaystyle\sum_{i=0}^{N-1} \bar{a}_{(i+j)\% N}\& \bar{b}_i =\displaystyle\sum_{i=0}^{N-1} \overline{a_{(i+j)\% N}|b_i} =\displaystyle\sum_{i=0}^{N-1} (1-(a_{(i+j)\% N}|b_i)) =N-\displaystyle\sum_{i=0}^{N-1} (a_{(i+j)\% N}|b_i).
因此,对于 0\leq j\leq N-1,我们可以将 \displaystyle\sum_{i=0}^{N-1} (a_{(i+j)\% N}|b_{i}) 计算为 \displaystyle\sum_{i=0}^{N-1} (a_{(i+j)\% N}|b_{i})=N-(\bar{a'}*\bar{b'})_{N-1+j},即一次卷积(时间复杂度为 O(N\log N))。
剩下的工作就是计算每个比特的这个值,得到 \displaystyle\sum_{i=0}^{N-1} (A_{(i+j)\% N}|B_i),并选择其中的最大值。在这里,总时间复杂度为 O(N\log N\log M))(其中 M=\max(a_0,a_1,\ldots,a_{N-1},b_0,b_1,\ldots,b_{N-1})),已经足够快了。
代码
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
int main() {
int n;
cin >> n;
vector <int> a(n), b(n), c(n), aa(n << 1), bb(n), cc;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i];
for (int j = 0; j < 5; j++) {
for (int i = 0; i < n; i++) {
aa[i] = (~a[i] >> j) & 1;
aa[n + i] = aa[i];
bb[n - i - 1] = (~b[i] >> j) & 1;
}
cc = convolution (aa, bb);
for (int i = 0; i < n; i++) {
c[i] += (n - cc[n + i - 1]) << j;
}
}
int ans = 0;
for (int i = 0; i < n; i++) ans = max(ans, c[i]);
cout << ans << endl;
return 0;
}
译自英文官方题解,并对卷积法做相关补充。