二进制双重求和 牛客练习赛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)*sum[i]^2 i=032(1<<i)sum[i]2

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

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值