地址:https://ac.nowcoder.com/acm/contest/4853#question
题意:中文不多解释啦。
解析:根据题意,有暴力:
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) sum+=a[i]&a[j];
但是1e5*1e5,1s过不去的。比赛时想了几个优化方法,但是无奈都过不了。赛后看了后才恍然大悟,只怪自己动手能力太差,惭愧惭愧!
首先&的运算,同为1,才为1,否则为0。对于结果,二进制只有1,1能贡献。看样例,全化成二进制是这样的:
对于a列来讲:模拟一下过程,可以得出9个1来,而本身是有3个1。对于b列,本身有2个1,可以&出4个1来。可以推测,每一位可&出1的数目是本身1数目的平方。上述样例可以得出:4 4 9,那么总结果就是4*2^2+4*2^1+9*2^0。所以开个数组来记录二进制每一位产生1的数目,最后加一下就好了。a[]记得开LL。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn=2e5+10; int main() { ll a[74]; int n; cin>>n; memset(a,0,sizeof(a)); int tot=0; for(int i=1;i<=n;i++) { ll x; cin>>x; tot=0; while(x) { if(x%2==1) a[tot]++; x=x/2; tot++; } } ll sum=0; for(ll i=0;i<66;i++) { sum+=a[i]*a[i]<<i; //<<i表示2^i次方 } cout<<sum<<endl; }
貌似是不需要快速幂的,ac了。