Codeforces 165E Compatible Numbers

Compatible Numbers

time limit per test:4 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output

Two integers x and y are compatible, if the result of their bitwise “AND” equals zero, that is, a & b = 0. For example, numbers 90 (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.

Examples

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

Tips

题意:

n n n 个正整数 a [ 1.. n ] a[1..n] a[1..n] ,满足 1 ⩽ a i ⩽ 4 × 1 0 6 1 \leqslant a_i \leqslant 4\times10^6 1ai4×106 ,请你对每个数都进行判断:其他数中是否存在和该数的与操作为 0 0 0 的数。若存在,则输出那个数,否则输出 − 1 -1 1

题解:

队友写过一回,觉得此题不错,收藏了。

该解法使用另一个数组 b [ i ] b[i] b[i] 保存与 i i i 按位与得 0 0 0 的数(且这个数在 a [ 1.. n ] a[1..n] a[1..n] 中出现)。

我们先设想一个最严苛的条件让两个数按位与得 0 0 0 ,即,两个数所有的位都相反。

而通过分析数据范围,我们知道, 2 21 &lt; 4 × 1 0 6 &lt; 2 22 2^{21} &lt;4\times10^6&lt;2^{22} 221<4×106<222 ,因此,可以取上界为 2 22 2^{22} 222 ,这样一来,一个数 i i i 的按位取反的数即为 2 22 − i 2^{22}-i 222i (原本为 0 0 0 的, 1 1 1 0 0 0 1 1 1 ;为 1 1 1 的, 1 1 1 1 1 1 0 0 0),记作 i − i^{-} i

初始情况即为, b [ ] b[] b[] 中保存了所有的 a [ i ] − a[i]^- a[i] 。然后,我们再通过缓和条件逐步找到所有 i i i 对应的 b [ i ] b[i] b[i]

为了缓和条件,我们先来分析一下 b [ i ] b[i] b[i] i i i 的关系(任意时刻),由定义出发, i i i 中的某一位如果为 1 1 1 b [ i ] b[i] b[i] 中的对应位置必为 0 0 0 ,否则任意。因此,将 i i i 中某些位的 0 0 0 变成 1 1 1 ,得到的新数 j j j ,和 i i i 共享一个 b [ i ] b[i] b[i] 。而易知 j &gt; i j&gt;i j>i ,因此需要从大到小去缓和条件。具体操作的时候,可以粗略地判断 b[i|1<<j] 是否有值,对时间复杂度不会有太大影响。

最后,只需看 b [ a [ i ] ] b[a[i]] b[a[i]] 是否有值即可。

Reference Code

#include <cstdio>
const int INF=(1<<22)-1;
const int MAXN=1e6+10;
int a[MAXN],b[INF+10];
int n;
int main(){
    scanf("%d",&n);
    for (int i=0;i<n;++i){
        scanf("%d",&a[i]);
        b[INF-a[i]]=a[i];
    }
    for (int i=INF;i>=0;--i){
        if (b[i]) continue;
        for (int j=0;j<22;++j){
            if (!b[i|1<<j]) continue;
            b[i]=b[i|1<<j];
            break;
        }
    }
    for (int i=0;i<n;++i)
        printf("%d%s",b[a[i]]?b[a[i]]:-1,i<n-1?" ":"\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值