题目
(石门强基题面)
有n个学生,编号1至n,第i个学生的品质是s[i]。
对于学生a和学生b来说,如果s[a] & s[b] 等于0(其中&就是二进制位操作的“与”),那么我们称a和b是"好伙伴"。
如果学生a有多个”好伙伴“,那么品质最好的那个就是a的”超级好伙伴"。
问题是: 对于任意的i(1<=i<=n),输出第i个学生的“超级好伙伴"的品质,如果第i个学生没有“好伙伴"输出-1.
思路
令,
则必然s^(M^s)=0
那么对于s[a],对其逐位取反,即M^s,称为s的反集;只需要使用子集dp查看其反集是否存在即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll z=1e6+9,K=22,M=(1<<K)-1;
ll n,s[z],f[M+9],ans;
void fastread()
{
ios::sync_with_stdio(0);
}
int main()
{
fastread();
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
f[s[i]]=s[i];
}
for(int i=0;i<K;i++)
{
for(int mask=0;mask<M;mask++)
{
if((mask>>i)&1)
{
if(!f[mask])f[mask]=f[mask-(1<<i)];
}
}
}
for(int i=1;i<=n;i++)
{
ans=f[M^s[i]];
if(ans)cout<<ans<<" ";
else cout<<-1<<" ";
}
return 0;
}