JZOJ4446

题目大意

有n个数,你可以进行任意次操作,每次操作如下:
将a与b两个数变为a and b与a or b两个数。

贪心

我们枚举四种不同情况,然后发现,一次操作的本质是把二进制上的1移走。
于是我们得到一个贪心算法:把1尽量往前挤。
具体看标程!

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int cnt[25],two[25];
int i,j,k,l,t,n,m;
ll ans;
int main(){
    two[0]=1;
    fo(i,1,19) two[i]=two[i-1]*2;
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&t);
        fo(j,0,19) 
            if ((t/two[j])%2==1) cnt[j]++;
    }
    fo(i,1,n){
        t=0;
        fo(j,0,19)
            if (cnt[j]){
                cnt[j]--;
                t+=two[j];
            }
        ans+=(ll)t*t;
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(JZOJ4446)