Codeforces 165E Compatible Numbers

本文探讨了一个算法问题,即寻找数组中两个整数进行位运算“AND”结果为零的情况,称为兼容数字。文章详细介绍了问题描述、输入输出格式、样例输入输出以及解题思路,包括如何利用二进制特性及数组存储技巧快速找到答案。

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) (1n106) — 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(1ai4106) — 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 ai4e6,所以ai的上界为 2 22 − 1 2^{22}-1 2221,记为 i n f inf inf
显然 i n f − a i inf-a_i infai表示将这个22位的二进制数上的0转化为1,1转化为0。
用数组 b i n f − a i b_{inf-a_i} binfai存放 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 &lt; &lt; j b_{i|1&lt;&lt;j} bi1<<j(j从0到22)(!!!非常精妙的想法orz,一开始的想法很复杂,需要分类),如果 b i ∣ 1 &lt; &lt; j ! = 0 b_{i|1&lt;&lt;j}!=0 bi1<<j!=0,那么 b i = b i ∣ 1 &lt; &lt; j b_i=b_{i|1&lt;&lt;j} bi=bi1<<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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值