cf1368D---贪心

题目链接: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出现的次数,具体见代码

 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 }
cf1368D
原文地址:https://www.cnblogs.com/edmunds/p/13216563.html