1 条题解

  • 0
    @ 2026-4-4 14:14:52

    我们考虑一对数 (ai,aj)(a_i, a_j) 需要满足条件

    ai & ajaiaja_i \ \&\ a_j \ge a_i \oplus a_j

    从二进制最高位向最低位逐位分析。设当前比较的位为第 kk 位(从高到低):

    • 若该位上两个数均为 00,则 ai&aja_i \& a_jaiaja_i \oplus a_j 在该位均为 00,继续比较下一位。
    • 若该位上一个是 00,另一个是 11,则该位上 ai&aj=0a_i \& a_j = 0aiaj=1a_i \oplus a_j = 1,因此 ai&aj<aiaja_i \& a_j < a_i \oplus a_j,条件不成立,可直接判定为假。
    • 若该位上两个数均为 11,则该位上 ai&aj=1a_i \& a_j = 1aiaj=0a_i \oplus a_j = 0,因此 ai&aj>aiaja_i \& a_j > a_i \oplus a_j,条件成立,且更高位已无影响,无需再考虑低位。

    pip_iaia_i 的二进制表示中最高位 11 所在的位置(从低到高编号,最低位为 00),pjp_j 类似。

    • pi>pjp_i > p_j,则在第 pip_i 位上 ai=1a_i = 1aj=0a_j = 0,由上述分析得 ai&aj<aiaja_i \& a_j < a_i \oplus a_j,条件不成立。
    • pi<pjp_i < p_j,同理条件不成立。
    • pi=pjp_i = p_j,则在最高位上两个数均为 11,于是 ai&aj>aiaja_i \& a_j > a_i \oplus a_j,条件成立。

    因此,条件成立的充要条件是 pi=pjp_i = p_j,即两个数的最高位位置相同。

    于是问题转化为:统计每个数的最高位 11 的位置,设 kk_\ell 表示最高位位置为 \ell 的数的个数,则答案等于所有组内两两组合数之和:

    k(k1)2\sum_{\ell} \frac{k_\ell \cdot (k_\ell - 1)}{2}

    实现时只需遍历数组一次,对每个数计算其最高位(例如使用 __builtin_clz__lg),累加对应计数,最后求和。时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)(因为 ai109a_i \le 10^9 对应最多 3030 个不同位)。

    C++ 代码框架

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            vector<int> cnt(31, 0); // 最高位可能为 0 ~ 30
            for (int i = 0; i < n; ++i) {
                int x;
                cin >> x;
                int hb = 31 - __builtin_clz(x); // 获取最高位位置 (0-based)
                cnt[hb]++;
            }
            long long ans = 0;
            for (int i = 0; i < 31; ++i) {
                long long c = cnt[i];
                ans += c * (c - 1) / 2;
            }
            cout << ans << '\n';
        }
        return 0;
    }
    
    • 1

    信息

    ID
    6349
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    1
    已通过
    1
    上传者