其实兰子大佬的题解已经很好很清楚了,我写这个只是为了方便我自己看。

想了很久按位计算贡献是什么意思。

套路就在于按位统计

int c[100]={0};
for(int i = 1; i <= n; i++) {
    long long x,b=0;
    scanf("%lld", &x);
    while(x) c[b++] += x & 1, x >>= 1;
}

这样就可以统计出来每一位1的个数,那么就是每一位0的个数。

这一位三元异或和为1的情况只有或者

然后对这两种情况累加一下,乘上对应的位数就好了。

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
inline long long C2(int x) { return 1LL * x * (x - 1) / 2; }
inline long long C3(int x) { return 1LL * x * (x - 1) * (x - 2) / 6; }
int main() {
    int n, c[100]={0};
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        long long x, b = 0;
        scanf("%lld", &x);
        while (x) c[b++] += x & 1, x >>= 1;
    }
    int bs = 1, ans = 0;
    for (int i = 0; i < 64; i++) {
        ans = (ans + (C3(c[i]) + 1LL * c[i] * C2(n - c[i])) % mod * bs) % mod;
        bs = (bs << 1) % mod;
    }
    cout << ans << endl;
}