Description
Data Constraint
Solution
对于一个数x,假如存在y,使得x⊆y,那么把y放在x前面一定不会使答案变差。所以我们设g[i]表示输入中包含i的数的个数(即i是该数子集)。设f[i]表示放到i时的答案。那么显然 f[i]=max(f[i],f[j]+(g[i]−g[j])∗i) 。( g[i]−g[j] 表示那些包含i但不包含j的数量,j表示与i只有一位不同的数且j>i)。时间复杂度O( NlogN ).
Code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=1e3;
ll a[maxn+5],f[maxn+5],g[maxn+5],n,i,t,j,k,l,x,ans,p;
int main(){
freopen("data.in","r",stdin);//freopen("and.out","w",stdout);
scanf("%lld",&n);
for (i=1;i<=n;i++)
scanf("%lld",&x),a[x]++,g[x]++;
for (j=0;j<=19;j++)
for (i=maxn-(1<<j);i>=0;i--)
if (!(i & (1<<j)))g[i]+=g[i+(1<<j)];
for (i=maxn;i>=1;i--){
f[i]=i*a[i];
for (j=0;j<20;j++){
if ((1<<j)+i>maxn) break;
if ((1<<j) & i) continue;
t=i+(1<<j);
f[i]=max(f[i],f[t]+i*(g[i]-g[t]));
}
ans=max(ans,f[i]);
}
printf("%lld\n",ans);
}