J—硝基甲苯之袭

题目链接:https://ac.nowcoder.com/acm/contest/95323/J

题意:

给定一个长度为n的数组,从中挑选两个数ai,aj(i<j),使其ai xor aj == gcd(ai,aj).求总方案数

思路:

由按位异或运算自反性可知,其实是求 ai xor gcd(ai,aj)== aj
aj通过枚举ai的因子(gcd必定是ai因子)来获得,再检查ai,aj的gcd是否是所枚举的因子即可
先求出顺序对+逆序对的总数,将其除以2便是答案
时间复杂度o(n*sqrt(n))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    int n;
    cin >> n;
    map<int, int> mp;
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        mp[x]++;
    }
    ll ans = 0;
    for (auto &it : mp) {
        int x = it.first;
        // 处理所有因数i
        for (int i = 1; i * i <= x; ++i) {
            if (x % i != 0) continue;
            // 检查i对应的y
            int y = x ^ i;
            if (mp.count(y) && __gcd(x, y) == i) {
                ans += (ll)it.second * mp[y];
            }
            // 检查另一个因数k = x/i
            int k = x / i;
            if (k == i) continue; // 避免重复处理
            y = x ^ k;
            if (mp.count(y) && __gcd(x, y) == k) {
                ans += (ll)it.second * mp[y];
            }
        }
    }
    cout << ans/2;
    return 0;
}
posted @ 2025-01-30 16:19  Marinaco  阅读(55)  评论(0)    收藏  举报
//雪花飘落效果