题目链接 Hiho 1496
设$f[i]$为二进制集合包含$i$的最大的两个数,这个东西用高维前缀和维护。
高位前缀和转移的具体方案 :枚举每一位,然后枚举每个集合,大的转移到小的。
注意合并的时候最好别用$std::sort$(我一开始被卡常数了)
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define fi first
#define se second
typedef long long LL;
typedef pair <int, int> PII;
int T;
int n;
int c[6];
PII f[(1 << 20) + 10];
LL ans;
inline void up(PII &a, PII b){
if (b.fi > a.fi){
a.se = a.fi;
a.fi = b.fi;
}
else if (b.fi > a.se){
a.se = b.fi;
}
if (b.se > a.fi){
a.se = a.fi;
a.fi = a.se;
}
else if (b.se > a.se){
a.se = b.se;
}
}
int main(){
scanf("%d", &T);
while (T--){
scanf("%d", &n);
memset(f, -1, sizeof f);
rep(i, 1, n){
int x;
scanf("%d", &x);
if (~f[x].fi) f[x].se = x;
else f[x].fi = x;
}
rep(i, 0, 19){
rep(j, 0, (1 << 20) - 1){
if ((1 << i) & j){
up(f[j ^ (1 << i)], f[j]);
}
}
}
ans = 0;
rep(i, 0, (1 << 20) - 1) if ((~f[i].fi) && (~f[i].se)) ans = max(ans, 1ll * i * f[i].fi * f[i].se);
printf("%lld\n", ans);
}
return 0;
}