牛客练习赛60 A.大吉大利

牛客练习赛60 A.大吉大利

题目链接

题目描述

给定n个整数,依次为 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an
∑ i = 1 n ∑ j = 1 n ( a i & a j ) \sum_{i = 1}^n\sum_{j = 1}^n(a_i\&a_j) i=1nj=1n(ai&aj)。“&”是二进制的与运算符。

输入描述:

第一行一个整数 n n n.
第二行 n n n 个整数 a i a_i ai

输出描述:

一个整数表示上述求和式的答案.

示例1

输入

5
1 2 3 4 5

输出

33

我对位运算太不敏感了……/(ㄒoㄒ)/~~
我们直接考虑答案的每一位1的个数,把每一个 a i a_i ai 的每一位都统计一下,对答案的某一位,如果有 k k k 个1,那实际上就是 k 2 k^2 k2 个1,模拟一下二进制加法即可,最后那个模拟加法用 1 < < i 1<1<<i 或者 p o w pow pow 好像都不对,要手写一个二次幂函数,AC代码如下:

#include 
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll bit[100];
void judge(ll n){
    ll cnt=0;
    while(n){
        bit[cnt++]+=n%2;
        n/=2;
    }
}

ll p(ll n){
    ll s=1;
    for(int i=0;i<n;i++)
        s*=2;
    return s;
}
 
int main(){
    fill(bit,bit+100,0);
    ll n,a[N];
    cin>>n;
    for(ll i=0;i<n;i++){
        cin>>a[i];
        judge(a[i]);
    }
    ll ans=0;
    for(ll i=0;i<100;i++){
        bit[i]=bit[i]*bit[i];
    }
    for(ll i=0;i<100;i++){
        bit[i+1]+=bit[i]/2;
        if(bit[i]%2==1) ans+=p(i);
    }
    cout<<ans;
}

你可能感兴趣的:(位运算,牛客)