给定n个数,要求求出两两异或值的和。位运算位与位之间是相互独立的,我们可以拆位来处理。对于第i位,显然只有0与1,1与0异或后有贡献答案 1<<i ,O(n)解决

#include<iostream>
#include<cmath>
#include<cstdio>
#define rep(i,j,k) for(register int i(j);i<=k;++i)
#define drp(i,j,k) for(register int i(j);i>=k;--i)
#define bug cout<<"~~~~~~~~~~~~~"<<'\n';
#define bugout(x) out(x,'\n');
typedef long long lxl;
template<typename T>
inline T max(T &a, T &b) {
return a > b ? a : b;
}
template<typename T>
inline T min(T &a, T &b) {
return a < b ? a : b;
}

inline char gt() {
static char buf[1 << 21], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
template <typename T>
inline void read(T &x) {
register char ch = gt();
x = 0;
int w(0);
while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
w ? x = ~(x - 1) : x;
}
template <typename T>
inline void out(T x, char cc) {
if(x < 0) x = -x, putchar('-');
char ch[20];
int num(0);
while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
while(num) putchar(ch[num--]);
putchar(cc);
}
const int N = 1e6 + 79;
int n;
int a[N];
lxl ans;
int bit[57];
int main() {
freopen("friendship.in", "r", stdin);
freopen("friendship.out", "w", stdout);
read(n);
rep(i, 1, n) {
read(a[i]);
rep(j, 0, 23) {
if(a[i] & (1 << j)) {
bit[j]++;//统计第j位为1的数字的个数
}
}
}
rep(j, 0, 23) {
ans += 1ll * bit[j] * (n - bit[j]) * (1ll << j);//第j位为0与1搭配的对数
}
out(ans, '\n');
return 0;
}


 ​