Codeforces 1368D AND, OR and square sum
算法讨论
起初的想法很简单,就是可以把所有数按从大到小排个序,然后就从左到右每个数依次考虑,到了第 i i i个数时,可以想到的是从高位考虑低位,如果是 1 1 1跳过,如果是 0 0 0那么肯定尽量要将这个搞成 1 1 1,怎么能最大化呢?考虑后面该位为 1 1 1的数为一个集合,那么该集合中与这个数 O R OR OR之后最大的那个数留下,刚开始思考的是会不会导致变小,发现如果小了后面更小的数如果此位为 1 1 1还是可以弥补过来的,再细看下,发现可以统计每位上的个数,然后将所有的 1 1 1排上去, 0 0 0排到下面,就类似于线代中那种行阶梯形那种亚子,最后就可以维护出答案啦。
算法实现
int n,cnt[25];
int main()
{
cin>>n;
for(int i=1,x;i<=n;i++){
cin>>x;
int tot=0;
while(x){
if(x&1)cnt[tot]++;
tot++,x>>=1;
}
}
ll ans=0;
while(233){
ll tmp=0,base=1;
int maxx=-1;
for(int i=0;i<20;i++){
if(cnt[i])tmp+=base,cnt [i]--;
base<<=1;
if(cnt[i])maxx=max(maxx,i);
}
ans+=tmp*tmp;
if(maxx==-1)break;
}
cout<<ans<<endl;
return 0;
}