CodeForces 165E Compatible Numbers(位运算 + 好题)

wo integers x and y are compatible, if the result of their bitwise "AND" equals zero, that is, a&b = 0. For example, numbers90(10110102) and 36(1001002) are compatible, as 10110102&1001002 = 02, and numbers 3(112) and 6(1102) are not compatible, as 112&1102 = 102.

You are given an array of integers a1, a2, ..., an. Your task is to find the following for each array element: is this element compatible with some other element from the given array? If the answer to this question is positive, then you also should find any suitable element.

Input

The first line contains an integer n (1 ≤ n ≤ 106) — the number of elements in the given array. The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 4·106) — the elements of the given array. The numbers in the array can coincide.

Output

Print n integers ansi. If ai isn't compatible with any other element of the given array a1, a2, ..., an, then ansi should be equal to -1. Otherwise ansi is any such number, that ai&ansi = 0, and also ansi occurs in the array a1, a2, ..., an.

Sample Input

Input
2
90 36
Output
36 90
Input
4
3 6 3 6
Output
-1 -1 -1 -1
Input
5
10 6 9 8 2
Output
-1 8 2 2 8
题意:给出 N 个数,在这个 N 个数中,如果存在 与 它 与操作为 0 的则输出那个数,否则输出-1;
分析: 对于一个数 53 (1 1 0 1 0 1) 先取反 得 ( 0 0 1 0 1 0)那么 与 53 与操作 为 0 的数 必定是 取反之后 1 位置的数 取0 或者取1都可以的。
一大神这样做的: dp[x] = y;表示 x 与 y 与 后为0, 那么 dp[x ^ Max] = x; 跟最大的数(全是1) 异或之后 就相当于取反,也就相当于 53 (1 1 0 1 0 1) 先取反 得 ( 0 0 1 0 1 0),然后就可以枚举每一个1的位置的值了, 从最大的开始 Max ,如果 dp[x]为0 那么就每一位枚举 看看 x 能否通过 将 某一位变成 1 之后 是不为 0 的;
也就是对于 53 来说 从 1 1 1 1 1 1 开始枚举,看看 是否某一位变成 1 就 可以和 0 0 1 0 1 0 一样了,然后得到 0 0 0 0 1 0和 0 0 1 0 0 0(此时这两个值已经存在),然后一值往下 找 改变一个值看看 是否跟存在的值一样
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int Max = (1 << 22) - 1; // 让 21 为全都1
 8 int dp[Max];
 9 int a[Max];
10 int main()
11 {
12     int n;
13     scanf("%d", &n);
14     memset(dp, 0, sizeof(dp));
15     for (int i = 0; i < n; i++)
16     {
17         scanf("%d", &a[i]);
18         dp[ a[i] ^ Max ] = a[i];  // 对每一数取反
19     }
20     for (int i = Max; i >= 0; i--)
21     {
22         if (!dp[i])  // 如果不是存在,看看是否能通过改变某一位
23         {
24             for (int j = 0; j < 22; j++)  //枚举
25             {
26                 if (dp[i|(1 << j)])
27                     dp[i] = dp[i | (1 << j)];
28             }
29         }
30     }
31     for (int i = 0; i < n - 1; i++)
32     {
33         if (dp[a[i]])
34             printf("%d ", dp[a[i]]);
35         else
36             printf("-1 ");
37     }
38     if (dp[a[n - 1]])
39         printf("%d
", dp[a[n - 1]]);
40     else
41         printf("-1
");
42 
43     return 0;
44 }
View Code
原文地址:https://www.cnblogs.com/zhaopAC/p/5479051.html