题目链接:https://codeforces.com/contest/1368/problem/D
题意:有n个数,每次可以选两个下标不同的数ai和aj,使得ai=ai|aj,aj=ai&aj,可以操作任意次,问操作后使得所有数最大的平方和是多少。
solution:仔细观察发现ai=ai|aj和aj=ai&aj如果对应的位不一样则交换0和1的位置,并没有改变当前位0和1的数量。因此我们可以统计出每个位上1的个数,然后重新分配1,越前面的尽可能分配越多的1,这样使得平方和更大。时间复杂度为O(N*log(ai)).
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
ll a[maxn]={0},cnt[maxn];
int main()
{
int n,x;
cin>>n;
for(int i=0;i<n;i++){
cin>>x;
for(int j=0;j<20;j++){
if((1<<j)&x) cnt[j]++;
}
}
for(int i=0;i<20;i++){
for(int j=0;j<n;j++){
if(cnt[i]<=0) break;
cnt[i]--;a[j]|=(1<<i);
}
}
ll ans=0;
for(int i=0;i<n;i++) ans+=a[i]*a[i];
cout<<ans;
return 0;
}