[CL-22] 异或和之和
二进制拆分。
对于枚举到的每一个二进制位 \(i\),注意到其对答案的贡献只有 \(0\) 和 \(2^{i}\) 两种情况
考虑什么时候贡献是 \(2^i\),可以发现,当选入奇数个该位为 \(1\) 的数之后,对答案的贡献是 \(2^{i}\)
因此变成求选出奇数个为 \(1\) 的数的方案数
设该位为 \(1\) 的数有 \(a\) 个,为 \(0\) 的数有 \(b\) 个,答案为 \(2^{b}\times\sum\limits^{a}_{i\in\{1,3,5,7\cdots\}}C^{i}_{a}\)
这样就可以做了,但是还有一个进一步的结论
\[\sum\limits^{a}_{i\in\{1,3,5,7\cdots\}}C^{i}_{a}=2^{a-1}
\]
不会证明,但是它是对的
复杂度 \(n\log(2^{31})\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p=1e9+7;
int power(int a,int t){
int base=a,ans=1;
while(t){
if(t&1){
ans=ans*base%p;
}
base=base*base%p;
t>>=1;
}
return ans;
}
int n;
int a[1000001];
int cnt0[33],cnt1[33];
signed main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
for(int j=1;j<=32;++j){
if(a[i]&1){
cnt1[j]++;
}
else{
cnt0[j]++;
}
a[i]>>=1;
}
}
int ans=0;
for(int i=1;i<=32;++i){
if(!cnt1[i]) continue;
ans+=power(2,cnt1[i]-1)*power(2,cnt0[i])%p*power(2,i-1)%p;
ans%=p;
}
cout<<ans<<endl;
}