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