目录:
题目:
分析:
对于这道题目的做法,小编觉得很玄,可以直接快排然后枚举暴力
O(n)
O
(
n
)
、又可双重循环求解
O(n2)
O
(
n
2
)
其实只是数据炒鸡水,而正解是
O(31∗n)
O
(
31
∗
n
)
,对于
31
31
是因为
a[i]
a
[
i
]
最大值为
2147483647
2147483647
,正是
231−1
2
31
−
1
然后考虑答案的性质:
Ans=a1∗20+a2∗21+a3∗23+…….+an∗2n−1
A
n
s
=
a
1
∗
2
0
+
a
2
∗
2
1
+
a
3
∗
2
3
+
…
…
.
+
a
n
∗
2
n
−
1
可见,答案中吗,高位的数选肯定比不选优。
那我们就考虑答案的倒数第i位是否可以选。
设当前Ans为比第i位高的所有二进制位选择的最优情况的和,那么如果第i位能选,就必定在这n个数中至少有两个数满足:
1:当前答案中的所有二进制为1的位置,在相应的这个数中的位置也为1(即ans & a=ans);
2:这个数的二进制第i位为1(即a & 2^(i-1)!=0)。ps.之所以是!=0,是因为&的结果不确定,只要当我们ta大于0时,就说明有值,也就是第i位为1
所以,我们只需从高位向低位扫一遍就可以了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int x[1000001];
int main()
{
int n=read();
for(int i=1;i<=n;i++) x[i]=read();
int ans=0;
for(int i=31;i>=1;i--)
{
int t=0;
for(int j=1;j<=n;j++)
if(((ans&x[j])==ans)&&((x[j]&(1<<(i-1)))!=0))
++t;
if(t>=2) ans+=(1<<(i-1));
}
cout<<ans;
fclose(stdin);
fclose(stdout);
return 0;
}