Codeforces 1368D AND, OR and square sum

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;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/107178384