Compatible Numbers
Time Limit :4 s
Memory Limit : 256 MB
Problem Description
Two integers x x x and y y y are compatible, if the result of their bitwise “AND” equals zero, that is, a a a & b b b = 0. For example, numbers 90 ( 101101 0 2 ) 90(1011010_2) 90(10110102) and 36 ( 10010 0 2 ) 36(100100_2) 36(1001002) are compatible, as 101101 0 2 1011010_2 10110102 & 10010 0 2 100100_2 1001002 = 0 2 0_2 02, and numbers 3 ( 1 1 2 ) 3(11_2) 3(112) and 6 ( 11 0 2 ) 6(110_2) 6(1102) are not compatible, as 1 1 2 11_2 112 & 11 0 2 110_2 1102 = 1 0 2 10_2 102.
Input
The first line contains an integer n n n ( 1 ≤ n ≤ 1 0 6 ) (1 ≤ n ≤ 10^6) (1 ≤ n ≤ 106) — the number of elements in the given array. The second line contains n space-separated integers a 1 , a 2 , , ⋯   , a n ( 1 ≤ a i ≤ 4 ⋅ 106 ) a_1, a_2, ,\cdots, a_n (1 ≤ a_i ≤ 4·106) a1, a2, ,⋯, an(1 ≤ ai ≤ 4⋅106) — the elements of the given array. The numbers in the array can coincide.
Output
Print n n n integers a n s i ans_i ansi. If a i a_i ai isn’t compatible with any other element of the given array a 1 , a 2 , . . . , a n a1, a2, ..., an a1, a2, ..., an, then a n s i ans_i ansi should be equal to − 1 -1 −1. Otherwise ansi is any such number, that a i ai ai & a n s i = 0 ans_i = 0 ansi = 0, and also a n s i ans_i ansi occurs in the array a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1, a2, ..., an.
Sample Input
input 1:
2
90 36
input 2:
4
3 6 3 6
input 3:
5
10 6 9 8 2
Sample Output
output 1:
36 90
output 2:
-1 -1 -1 -1
output 3:
-1 8 2 2 8
Tips
题意:
给定一个序列
a
1
,
⋯
 
,
a
n
a_1,\cdots,a_n
a1,⋯,an,对于ai,如果存在与
a
i
a_i
ai进行与操作为
0
0
0的数
a
j
a_j
aj,则输出
a
j
a_j
aj,否则输出
−
1
-1
−1。
题解:
a
i
≤
4
e
6
a_i≤4e6
ai≤4e6,所以ai的上界为
2
22
−
1
2^{22}-1
222−1,记为
i
n
f
inf
inf。
显然
i
n
f
−
a
i
inf-a_i
inf−ai表示将这个22位的二进制数上的0转化为1,1转化为0。
用数组
b
i
n
f
−
a
i
b_{inf-a_i}
binf−ai存放
a
i
a_i
ai。
对于
b
i
b_i
bi(
i
i
i从
i
n
f
inf
inf到0),如果
b
i
b_i
bi=0,则遍历
b
i
∣
1
<
<
j
b_{i|1<<j}
bi∣1<<j(j从0到22)(!!!非常精妙的想法orz,一开始的想法很复杂,需要分类),如果
b
i
∣
1
<
<
j
!
=
0
b_{i|1<<j}!=0
bi∣1<<j!=0,那么
b
i
=
b
i
∣
1
<
<
j
b_i=b_{i|1<<j}
bi=bi∣1<<j。
最后输出只需要遍历
b
a
i
b_{a_i}
bai的值即可。
Reference Code
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1000005;
const int INF=(1<<22)-1;
int a[maxn],b[INF+5];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
b[INF-a[i]]=a[i];
}
//printf("pass\n");
for(int i=INF;i>=0;i--)
if(b[i]==0){
int flag=0;
for(int j=0;j<22;j++){
/* 开始的写法
if((1<<j)<=i){
if(b[max(i,i^(1<<j))]){
b[i]=b[max(i,i^(1<<j))];
flag=1;
}
}
else if(b[i+(1<<j)]){
b[i]=b[i+(1<<j)];
flag=1;
}
*/
if(b[i|1<<j]){ //精妙的写法orz
b[i]=b[i|1<<j];
flag=1;
}
if(flag)break;
}
}
//printf("pass\n");
for(int i=0;i<n-1;i++)
if(b[a[i]])
printf("%d ",b[a[i]]);
else
printf("-1 ");
if(b[a[n-1]])
printf("%d\n",b[a[n-1]]);
else
printf("-1\n");
return 0;
}