异或的性质与应用

异或:

任意一个数都可以表示成二进制的状态,那么两个数在二进制状态下,
进行异或运算: 相同得 0 ,反之 得 1。
a b ^
1 1 1
1 0 0
0 1 0
0 0 1

性质:

1、交换律: A ^ B = B ^ A
2、结合律:(A ^ B) ^ C = A ^ (B ^ C)
3、恒等律:X ^ 0 = X; 
4、归零律:X ^ X = 0;
5、自反:A ^ B ^ B = A ^ 0 = A;
6、 对于任意的 X: X ^ (-1) = ~X;
7、 如果 A ^ B = C 成立,那么 A ^ B = C,B ^ C = A;

应用:

1. 1-1000放在含有1001个元素的数组中,只有唯一的一个元素重复,找出这个重复的数字。要求不能使用辅助存储空间并且数组的每个元素只能访问一次。
法一:
将这1001个元素加起来的和减去1+2+……+1000,所得的值就是重复的数字(数据过大容易溢出)。
法二:异或
将1001个数全部异或得到的值再与1^2^……^1000的结果再次异或,这样就避免了数据过大溢出的情况。
首先,异或运算满足交换律和结合律,即a^b = b^a,(a^b)^c = a^(b^c)。令重复的数字为n:
所以1 ^ 2 ^ … ^ n ^ n ^ … ^ 1000 = 1 ^ 2 ^ … ^ 1000 ^ (n ^ n) = 1 ^ 2 ^ … ^ 1000 ^ 0 = 1 ^ 2 ^ … ^ 1000(即序列中除了重复数字 n 以外所有数的异或。
如果令1 ^ 2 ^ … ^ 1000(序列中不包含n)的结果为T,那么1 ^ 2 ^ … ^ 1000(序列中包含n)的结果就是 T^n,T ^ (T ^ n) = n。
法三: map
用 map 判断某个元素是否已经出现过

2. 变形:一个数组存放若干整数,一个数出现奇数次,其余数均出现偶数次,找出这个出现奇数次的数。
奇数次 : A ^ A ^ A = A ^ 0 = A
偶数次 :B ^ B = 0
将所有值异或即可解决。

3、给出n个数,会有q次询问,每次询问[L, R] 区间内所有出现次数为奇数的数的异或,如果这个区间内没有出现次数为奇数的数,那么输出0。
与第二道应用类似,只是这里多了一个区间。
其实与前缀和类似,我们可以求其前缀异或和 : sum[i] = sum[i - 1] ^ a[i]
就可以得到某个区间的异或值 : sum[R] - sum[L - 1]
为什么这个成立呢 ?
假设 [1,L - 1] 的每个元素是 a1,a2,a3......a(L - 1)
     [L,R] 的每个元素是    a1,a2,a3.......a(L- 1).....a[R]
将上下进行异或,最后就留下 L - R 这个区间的异或值.

参考博客:https://blog.csdn.net/Jasmineaha/article/details/81412711

原文地址:https://www.cnblogs.com/prjruckyone/p/12302732.html