1 solutions

  • 0
    @ 2025-4-29 20:33:12

    我们可以把问题简化为逐位分析每个二进制位对最终异或和的贡献,因为异或运算的每一位是独立的,且加法在二进制下每一位的贡献可以单独计算。具体步骤如下:

    11 . 统计每一位的出现次数

    首先,对于数组中的每个数,我们观察它的每一个二进制位(从第 00 位,即最低位开始,到第 2929 位,这里处理到 3030 位足够)。 定义 cnt[i]cnt[i] 为数组中所有数的第 ii 位是 11 的数的个数。 例如,数组 [3,5][3, 5](二进制是 1111101101),第 00 位的 cnt[0]cnt[0]11(只有 33 的第 00 位是 11),第 11 位的 cnt[1]cnt[1]00,第 22 位的 cnt[2]cnt[2] 是 2(两个数的第 22 位都是 11)。

    22. 对每个数计算异或和的贡献

    对于数组中的每一个数 a[k]a[k],我们逐位分析它与数组中所有数的异或结果对总和的贡献: 假设当前分析第 ii 位: 如果 a[k]a[k] 的第 ii 位是 00: 当它与其他数 a[j]a[j] 异或时,第 ii 位为 11 的条件是 a[j]a[j] 的第 ii 位是 11(因为 01=10⊕1=1)。 这样的 a[j]a[j] 共有 cnt[i]cnt[i] 个,每个这样的异或结果在第 ii 位贡献 11,对应的数值贡献是 cnt[i]×(1<<i)cnt[i] × (1 << i)(因为第 ii 位的权重是 2i2^i)。 如果 a[k]a[k] 的第 ii 位是 11: 当它与其他数 a[j]a[j] 异或时,第 ii 位为 11 的条件是 a[j]a[j] 的第 ii 位是 00(因为 10=11⊕0=1)。 这样的 a[j]a[j] 共有 ncnt[i]n - cnt[i] 个(总共有 n 个数,减去第 ii 位是 11cnt[i]cnt[i] 个),对应的数值贡献是 (ncnt[i])×(1<<i)(n - cnt[i]) × (1 << i)

    33. 累加每一位的贡献得到总和

    对每个数 a[k]a[k],遍历所有 3030 位(002929),根据上述规则计算每一位的贡献并累加,得到这个数与所有数的异或和。最后找出所有数中最大的异或和即可。

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    
    void solve() {
        int n; cin >> n;
        int arr[n+1];
        vector<int> cnt(30, 0);
        for (int i = 1; i <= n; i++) {
            cin >> arr[i];
            for (int j = 0; j < 30; j++) {
                cnt[j] += ((arr[i] >> j) & 1);
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            int tot = 0;
            for (int j = 0; j < 30; j++) {
                bool f = ((arr[i] >> j) & 1);
                if (f) tot += (1 << j) * (n - cnt[j]);
                else tot += (1 << j) * cnt[j];
            }
            ans = max(ans, tot);
        }
        cout << ans << "\n";
    }
    
    signed main() {
        solve();
        return 0;
    }
    
    • 1

    Information

    ID
    1466
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    8
    Tags
    (None)
    # Submissions
    86
    Accepted
    10
    Uploaded By