举个例子把,比如我选3和5操作,二进制分别是011,101
二进制&后是001,丢失了3的第二位二进制
二进制∣后是111,增加了5的第二位二进制
发现了什么!!!操作后二进制每一位上的1总数不变!!
那我们大胆的贪心,统计二进制每一位上的1数量
然后假设最后操作完,每一个数都尽可能大,也就是只要这一位还有1,就加上去
构造正确性证明
也许你有疑问,最后能不能存在我们构造的这种结果呢?
肯定有!!你要记住操作不改变原有1的数量
只要当前构造的数还没有覆盖全部的1,就应该去和那个有1的数操作
贪心正确性证明(只是感性证明)
比如两个二进制,11111111111111110和01111111111111111
&后是0,∣后是11111111111111111
看起来好亏呀!!损失了那么大个数的平方,只增加了1
实际上计算一下发现这样还是更优的
虽然这样并不能算是证明.....但是就是做题的一种方法呀.....
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
ll n,a[maxn],b[maxn],xi[maxn],ans;
int main()
{
cin >> n;
for(int i=1;i<= n;i++)
{
cin >> a[i];
int x=1;
while(a[i])
{
if(a[i]&1) b[x]++;
a[i]>>=1;
x++;
}
}
xi[1]=1;
for(int i=2,len=1;i<=30;i++) len*=2, xi[i]=len;
for(int i=1;i<=n;i++)
{
ll x=0;
for(int j=1;j<=30;j++)
if(b[j]) b[j]--,x+=xi[j];//贪心,有1就加上去
ans+=x*x;
}
cout << ans;
}