JZOJ 4937【GDKOI2017模拟1.12】与运算

来源:互联网 发布:工业设计 比赛软件 编辑:程序博客网 时间:2024/05/29 21:30

Description

这里写图片描述

Solution

有一个很显然的性质就是如果一个x的所有二进制位都≥y的所有的二进制位,那么x肯定放在y的前面会比较优。
所有我们设f[i]表示填i时的最大答案。
我们设sum[i]表示二进制包含i到数的个数。
那么f[i]=max(f[i],f[i|er[j1]]+i(sum[i]sum[i|er[j1]]))
每次只改动一位,因为要考虑所有的i的贡献,所以所有的i都要做。

Code

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=2e6+7;ll i,j,k,l,t,n,m,ans,da;ll a[maxn],f[maxn],er[21],sum[maxn];int main(){    freopen("and.in","r",stdin);    freopen("and.out","w",stdout);    scanf("%d",&n);    fo(i,1,n)scanf("%d",&k),da=max(da,k),a[k]++;    er[0]=1;fo(i,1,20)er[i]=er[i-1]*2;      fo(i,1,da)sum[i]=a[i];    fo(j,1,20){        fod(i,da,1){            if((i&er[j-1])==0)continue;            sum[i-er[j-1]]+=sum[i];            }    }    fod(i,da,1){        f[i]=a[i]*i;        fo(j,1,20){            if((i&er[j-1])!=0)continue;            f[i]=max(f[i],f[i|er[j-1]]+i*(sum[i]-sum[i|er[j-1]]));        }        ans=max(ans,f[i]);    }    printf("%lld\n",ans);}
1 0
原创粉丝点击