分析
对于 \(a\&b=0\),我们发现,将 \(b\) 与 \(2^{22}-1\) 异或的值,它与 \(a\) 取并的值仍为 \(a\),于是我们发现我们所求的就是 \(a_i\oplus2^{22}-1\&a_j=a_j\),这个思路就显而易见的是类似于高维前缀和。
我们发现对于如果 \(i\) 的第 \(j\) 位为0,那么和它取与等于它的数,和它在这一位改为1的数取与的结果也为那个数本身。
因此转移方程就显然了。
最后对于每个数的答案,就以第一段发现的性质,取 \(dp[a_i\oplus2^{22}-1]\) 即可。
代码
#include<bits/stdc++.h>
using namespace std;
int n,f[5000001],k,a[1000005];
inline void read(int &res){
res=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
res*=f;
}
int main()
{
read(n);
k=log2(4000000)+1;
for(int i=1;i<=n;i++){
read(a[i]);
f[a[i]]=a[i];
}
for(int j=0;j<k;j++){
for(int i=1;i<(1<<k);i++){
if(!f[i])continue;
if(!(i&(1<<j)))f[i^(1<<j)]=f[i];
}
}
k=(1<<k)-1;
for(int i=1;i<=n;i++){
if(!f[a[i]^k])puts("-1");
else printf("%d\n",f[a[i]^k]);
}
return 0;
}