异或和之和 异或问题

题目
有n个数,任选3个进行异或,求出所有三元组的异或和的和

普通计算是\(O(n^3)\)
但是发现,对于异或的运算,就转换为二进制的运算,把每一个数组转换为二进制,
再拆分,当且仅当$1 ⊕ 1 ⊕1 $和\(1⊕0⊕0\)时,答案才为1,否则都是0,也就是说,只有这两个情况是由贡献的
把每个数字化为二进制,然后统计每位上1的个数,变成组合数学问题,设cnt[i],表示第i位1的个数,那么答案就是\(C_{cnt[i]}^3 + C_{cnt[i]} ^ 1 * C_{n - cnt[i]}^2\)

#include<iostream>
using namespace std;
#define ll long long
const int mod = 1000000007;
ll a[1000010];
ll t[64];
ll power(ll a,ll b){
    ll res = 1;
    while(b){
        if(b & 1)res = res * a % mod;
        b >>= 1,a = a * a % mod;
    }
    return res;
}
ll inv(ll x){
    return power(x, mod - 2);
}
ll C(ll n, ll m){
    if(n < m)return 0;
    ll res = 1;
    for(ll i = 0; i < m; i++)
    	res = res * (n - i) % mod, res = res * inv(i + 1) % mod;
    return res;
}
int main(){
    ll n, m, x;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> x;
        int j = 0;
        while(x){
            if(x & 1)t[j]++;
            j++,x >>= 1;
        }
    }
    ll sum = 0;
    for(int i = 0; i < 64; i++){
        sum += (1LL << i) % mod * (C(t[i], 3) + C(n - t[i], 2) * t[i] % mod) % mod;
        sum %= mod;
    }
    cout << sum;
}

猜你喜欢

转载自www.cnblogs.com/Emcikem/p/12909983.html