题目链接
题目大意
题目思路
首先上一个暴力代码(会t)了解一下题目
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,a[maxn];
ll ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans+=a[i]&a[j];
}
}
printf("%lld",ans);
return 0;
}
首先明白了题目的意思,暴力肯定t,其实有关位运算的题目要一般都要考虑贡献问题,往那方面思考,很快就会有答案。
我们直接考虑答案的每一位1的个数,把每一个 ai的每一位都统计一下,对答案的某一位,如果有 k 个1,那实际上就是 k^2个1,模拟一下二进制加法即可.
代码
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,a[maxn],cnt[40];
ll ans,sum;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
for(int j=0;j<=30;j++){
if(a[i]&1<<j){
cnt[j]++;
}
}
}
for(int i=0;i<=30;i++){
ans+=1ll*(1<<i)*cnt[i]*cnt[i];
}
printf("%lld",ans);
return 0;
}