传送门

题意

给出 n n n个数 a i a_i ai,为每个 a i a_i ai找到一个 a j a_j aj使得 a i & a j = = 0 a_i\&a_j==0 ai&aj==0,若不存在输出 − 1 -1 1

其中 n , a i n,a_i n,ai均小于 4 ∗ 1 0 6 4*10^6 4106


SOSDP

因为 s o s d p sosdp sosdp求的是 f [ m a s k ] = ∑ i & m a s k = i a i f[mask]=\sum\limits_{i\&mask=i}a_i f[mask]=i&mask=iai

现在只需要把定义换一下, f [ m a s k ] f[mask] f[mask]装的是某个 m a s k mask mask子集的数字

那么对每个 a i a_i ai来说,需要找到某个 a j a_j aj a i a_i ai完全没有交集

转化一下,就是 a j a_j aj a i a_i ai补集的子集

所以答案为 f [ ∼ a i ] f[\sim a_i] f[ai]

再说一下 f f f数组的初始化

即当所有二进制都和 m a s k mask mask相同时的答案, f [ m a s k ] = m a s k f[mask]=mask f[mask]=mask

前提是 m a s k mask mask这个数字存在,否则仍然无法作为答案

#include <bits/stdc++.h>
using namespace std;
const int mx = 1<<22;
int n,a[mx],f[mx];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)	scanf("%d",&a[i] ),f[a[i]] = a[i];
	for(int i=0;i<22;i++) 
	for(int j=0;j<mx;j++)
	{
		if( f[j] )	continue;//已经找到了答案 
		if( j&(1<<i) )	f[j] = f[j^(1<<i)];
	}
	for(int i=0;i<mx;i++)	if( !f[i] )	f[i] = -1;
	for(int i=1;i<=n;i++)	printf("%d ",f[(mx-1)^a[i]]);
}