JZOJ4446. 【HNOI2016模拟4.14】B

来源:互联网 发布:微积分 清华 知乎 编辑:程序博客网 时间:2024/06/06 10:06

这里写图片描述

分析

通过观察样例,推理得出结论:改变之后的平方和更大。
认真分析改变两个数的意义:
就是将小的数二进制某些位的1移到大的那个数那里,然后这个位置变为0。
我们也知道,一个数越大,它的平方越大。

我们只需要记录二进制下每一个位置一共有多少个1,然后每次取最大的数,
这样的答案一定是最优的。

code

#include <cstdio>#include <algorithm>#include <cstring>#include <string.h>#include <cmath>#include <math.h>#define N 100003#define ll long long using namespace std;ll a[N][23],z[23],sum,ans;int num[23],n,x,now;char ch;void read(int &n){    n=0;    ch=getchar();    while((ch<'0' || ch>'9') && ch!='-')ch=getchar();    int w=1;    if(ch=='-')w=-1,ch=getchar();    while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=getchar();    n*=w;}int main(){    z[0]=1;    for(int i=1;i<20;i++)        z[i]=z[i-1]*2;    read(n);    for(int i=1;i<=n;i++)    {        read(x);        for(int j=0;j<20;j++)            if((x&z[j])>0)num[j]++;    }    for(int k=19;k>=0;k--)        for(int i=1;i<=num[k];i++)            a[i][k]=1;    for(int i=1;i<=n;i++)    {        sum=0;        for(int j=0;j<20;j++)            sum+=z[j]*a[i][j];        ans+=sum*sum;    }    printf("%lld\n",ans);}
原创粉丝点击