其实兰子大佬的题解已经很好很清楚了,我写这个只是为了方便我自己看。
想了很久按位计算贡献是什么意思。
套路就在于按位统计
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; }