二进制双重求和 牛客练习赛60 A题 大吉大利

大吉大利

题目描述
在这里插入图片描述
输入描述:

第一行一个整数n.
第二行n个整数ai.

输出描述:

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


可以这样去思考,把一个数拆为二进制去进行求和运算,

例如:

001、010、011、100、101

拿第一个数(001)开始运算,第一位的 1 进行了5次运算;拿第二个数(010)开始运算,第二位的 1 进行了5次运算;拿第三个数(011)开始运算,第二三位的 1 进行了5次运算…

而对于每一位 1 来说,&运算如果跟 1 进行,那么是不变的;所以可以看出只要记录这些数的每一个二进制位 1 的个数,就可以算出答案;

ans= ∑ i = 0 32 ( 1 < < i ) ∗ s u m [ i ] 2 \sum_{i=0}^{32} (1<i=032(1<<i)sum[i]2

sum[i]表示所有数 i 进进制位 1 的个数

代码:

#include
#define LL long long
#define pa pair
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=100010;
const int M=2000100;
const LL mod=2e9;
int a[N],s[32];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		for(int j=0;j<32;j++){
			if((1<<j)&a[i]) s[j]++;
		}
	}
	LL ans=0;
	for(int i=0;i<32;i++){
		ans+=(1ll*s[i]*s[i]*(1ll<<i));
	}
	cout<<ans<<endl;
	return 0;
}

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