题意为:选一个长度为k的子序列,计为集合s, 若s中,二进制下第i位,至少有max(1,k-2)个数是1,则获得 2^i的贡献。
求出最大贡献。(子序列集合任选)
一看这题直接莽按位从高到底枚举处理,但会发现,每一位会剩至多2个元素可变。。(即高位没选,但低位可以选)
不好处理(暴力应该可以处理,比较麻烦:先选出最高位,然后选出符合条件的次高位,然后改变可变元素剩余数量,再一次往低位枚举)
不过这题有更简单的做法:
考虑集合size>=3的情况,即集合中,二进制下,第i位都最多只能有2个0,即任意三个数在第i位的或,都必须为1。
那么任取集合中的三个数,他们或的结果,即集合的贡献(因为每一位有贡献的,任取三个或一定为1).
到这里就显然有:任选三个数,求他们的或,即贡献。枚举求出最大的即可。
(这里下标重复表示选1个或2个)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
ll a[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
ll mx=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
{
mx=max(mx,a[i]|a[j]|a[k]);
}
cout<<mx<<endl;
return 0;
}