分析

对于 \(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;
}
posted on 2021-06-25 17:20  漠寒·  阅读(59)  评论(0编辑  收藏  举报