题目链接:https://codeforces.com/problemset/problem/1368/D
简单题意:对于ai=x,aj=y,定义操作:ai=x&y,aj=x|y。对给定数列中任意两个元素执行操作任意次,求S=Σai^2的最大值
这个操作其实就是把ai的二进制下1的位移到aj上(如果aj对应位为0)。整个过程中和不变,要使得平方和最大,就要是大的数尽量大。于是可以考虑尽可能的进行操作转移1。形象的说可以脑补一个图:一个宽度为20就是最长位数,高度为n的数组,让每个1尽量下落,堆到最底下,可以使得平方和最大。从而只要考虑每个位置1出现的次数,具体见代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=200+10; 5 6 ll sum,ans,r,a[maxn],b[30]; 7 int n,i,j,k; 8 9 int main(){ 10 scanf("%d",&n); 11 for (i=1;i<=n;i++) scanf("%lld",&a[i]); 12 for (i=1;i<=n;i++){ 13 for (j=20;j>=0;j--) 14 if (a[i]&(1<<j)) b[j]++; 15 } 16 ans=0; 17 for (i=1;i<=n;i++){ 18 ll res=0;int f=0; 19 for (j=20;j>=0;j--) 20 if (b[j]>0){ 21 res+=(1<<j);b[j]--; 22 f=1; 23 } 24 if (f==0) break; 25 ans+=(res*res); 26 } 27 printf("%lld ",ans); 28 //system("pause"); 29 return 0; 30 }