有n个数,你可以进行任意次操作,每次操作如下:
将a与b两个数变为a and b与a or b两个数。
我们枚举四种不同情况,然后发现,一次操作的本质是把二进制上的1移走。
于是我们得到一个贪心算法:把1尽量往前挤。
具体看标程!
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int cnt[25],two[25];
int i,j,k,l,t,n,m;
ll ans;
int main(){
two[0]=1;
fo(i,1,19) two[i]=two[i-1]*2;
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&t);
fo(j,0,19)
if ((t/two[j])%2==1) cnt[j]++;
}
fo(i,1,n){
t=0;
fo(j,0,19)
if (cnt[j]){
cnt[j]--;
t+=two[j];
}
ans+=(ll)t*t;
}
printf("%lld\n",ans);
}