举 个 例 子 把 , 比 如 我 选 3 和 5 操 作 , 二 进 制 分 别 是 011 , 101 举个例子把,比如我选3和5操作,二进制分别是011,101 举个例子把,比如我选3和5操作,二进制分别是011,101
二 进 制 & 后 是 001 , 丢 失 了 3 的 第 二 位 二 进 制 二进制\&后是001,丢失了3的第二位二进制 二进制&后是001,丢失了3的第二位二进制
二 进 制 ∣ 后 是 111 , 增 加 了 5 的 第 二 位 二 进 制 二进制|后是111,增加了5的第二位二进制 二进制∣后是111,增加了5的第二位二进制
发 现 了 什 么 ! ! ! 操 作 后 二 进 制 每 一 位 上 的 1 总 数 不 变 ! ! 发现了什么!!!操作后二进制每一位上的1总数不变!! 发现了什么!!!操作后二进制每一位上的1总数不变!!
那 我 们 大 胆 的 贪 心 , 统 计 二 进 制 每 一 位 上 的 1 数 量 那我们大胆的贪心,统计二进制每一位上的1数量 那我们大胆的贪心,统计二进制每一位上的1数量
然 后 假 设 最 后 操 作 完 , 每 一 个 数 都 尽 可 能 大 , 也 就 是 只 要 这 一 位 还 有 1 , 就 加 上 去 然后假设最后操作完,每一个数都尽可能大,也就是只要这一位还有1,就加上去 然后假设最后操作完,每一个数都尽可能大,也就是只要这一位还有1,就加上去
构造正确性证明
也 许 你 有 疑 问 , 最 后 能 不 能 存 在 我 们 构 造 的 这 种 结 果 呢 ? 也许你有疑问,最后能不能存在我们构造的这种结果呢? 也许你有疑问,最后能不能存在我们构造的这种结果呢?
肯 定 有 ! ! 你 要 记 住 操 作 不 改 变 原 有 1 的 数 量 肯定有!!你要记住操作不改变原有1的数量 肯定有!!你要记住操作不改变原有1的数量
只 要 当 前 构 造 的 数 还 没 有 覆 盖 全 部 的 1 , 就 应 该 去 和 那 个 有 1 的 数 操 作 只要当前构造的数还没有覆盖全部的1,就应该去和那个有1的数操作 只要当前构造的数还没有覆盖全部的1,就应该去和那个有1的数操作
贪心正确性证明(只是感性证明)
比 如 两 个 二 进 制 , 11111111111111110 和 01111111111111111 比如两个二进制,11111111111111110和01111111111111111 比如两个二进制,11111111111111110和01111111111111111
& 后 是 01111111111111111 , ∣ 后 是 11111111111111111 \&后是01111111111111111,|后是11111111111111111 &后是01111111111111111,∣后是11111111111111111
看 起 来 好 亏 呀 ! ! 损 失 了 那 么 大 个 数 的 平 方 , 只 增 加 了 1 看起来好亏呀!!损失了那么大个数的平方,只增加了1 看起来好亏呀!!损失了那么大个数的平方,只增加了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;
}