异或的神奇性质
异或作为特殊的运算方式,是非常nb的,它没有与、或的偏向性,是平衡的,可以自消,可以组合,是非常神奇的一类方式,也是因为这个,异或有诸多性质。
自消
异或非常神奇有:\(a \oplus a = 0,\ a \oplus b \oplus a = b\),这种形式就非常方便进行类似差分式的消去,可以利用前缀和来求出来一段的异或和。
前 n 项的异或和
即 \(S_n = 1 \oplus 2 \oplus \ldots \oplus n\),通过打表可以得出来下面的输出:
1 1
2 3
3 0
4 4
5 1
6 7
7 0
8 8
9 1
10 11
11 0
12 12
13 1
14 15
15 0
16 16
17 1
18 19
19 0
20 20
我们发现异或和可以每四个一组分成下面这种情况:
1 3 0 4
1 7 0 8
1 11 0 12
1 15 0 16
1 19 0 20
这是有规律的循环节,可以发现当一个性质,假设 \(n | 4\),那么一个循环节为 \(1, n - 1, 0, n\)。
利用这个性质就可以快速求出前 \(n\) 项异或和,又因为,本身异或和有自消的性质,于是有:
所以说打表在很多情况下有奇效。
虽然说的找规律找出来的,但是为什么有这种规律呢,很难说,只能说去模拟去感受感受。
自反异或
突发奇想想出来的,既然前缀异或和有规律,那么 \(n\oplus -n\) 有什么规律呢。打表出来,貌似还真有点说法:
1 -2
2 -4
3 -2
4 -8
5 -2
6 -4
7 -2
8 -16
9 -2
10 -4
11 -2
12 -8
13 -2
14 -4
15 -2
16 -32
17 -2
18 -4
19 -2
20 -8
21 -2
22 -4
23 -2
24 -16
25 -2
26 -4
27 -2
28 -8
29 -2
30 -4
31 -2
32 -64
33 -2
34 -4
我们可以发现一个性质,设 \(n = k * 2^u\),\(k\) 的因子不含 \(2\),那么有 \(n \oplus -n = -2^{u + 1}\)。这个也是同理不好证明,但是模拟可以理解一些意思。(测试 \(10^9\) 里面的全符合的)。
也就是说,通过这个操作我可以很快的求出一个数有几个 \(2\) 因子。也就是 \(\operatorname O(\log n)\) 甚至 \(\operatorname O(1)\) 的求出一个数有几个 \(2\) 的因子。__builtin_ctz(i) 可以直接求二进制末尾连续有多少个 0,也就是变相求出来有 \(i\) 有几个 \(2\) 因子。
从这里开可以再试试别的方法形成的序列,比如 i ^ (i - 1) 或者别的什么,可以发现都或多或少有某些规律。
所以说我们可以得到一个不算严谨的规律,有两个及以上规律变化的变量参与的异或运算得到的序列,一定是一个有规律序列。这是一种经验规律,也是异或这种操作 “平衡性” 的体现。
同时还有一点,像是 \(i\) 和 \(i + 1\) 这种数字是有非常强的规律的,他们形成的序列也多半是规律序列。对于这些规律序列,证明是很困难的了,所以要善用打表。
拼凑异或
异或本质上是相同为 \(0\),不同为 \(1\),因此如果一个数恰好是 \(2^k\),那么只要 \(2^u\) 不和 \(2^k\) 相等,那么就有 \(2^k \oplus 2^u = 2^k + 2^u\),基于这个原理,我们可以拆分一个数字,我们知道一个十进制的数字,以可以写成二进制的形式 ,那么一个数就可以通过这些二进制位上的 1 拆开成一堆 \(2^k\) 异或的形式。如:
通过把一个数的异或给散开,可以让我们找到一些更本质的性质,从而解决问题。
零异或
众所周知,异或是不同为 \(1\),相同为 \(0\),那么如果直接异或 \(0\) 或者 \(1\) 的话会如何?有下表:
0 0 = 0
0 1 = 1
1 0 = 1
1 1 = 0
可以发现异或 \(0\) 的话可以保留原值,异或 \(1\) 的话是取相反数,利用这个性质可以有很多玩法。
同时,这个操作也像是不进位的加法,用处多多。
异或
异或 ^,它有个性质,即 a ^ b == (a | b) - (a & b)。
推导:异或的运算方法就是相同为 \(0\),不同为 \(1\)。我们把它和或运算相比,可以发现,除非两位上都是 \(1\),否则 ^ 和 | 的结果是相同的。 而对于都为 \(1\) 的情况,异或为 \(0\),或为 \(1\),因此我们可以看做,异或就是或运算之后减去了都为 \(1\) 的位的数。而恰好,两位都为 \(1\) 的情况就是与,因此我们可以得到 a ^ b == (a | b) - (a & b)。
从某种方面说,异或就是不进位的加法。
异或具有交换律,结合律。其中交换律比较显然(数的先后关系不影响运算结果)。下面证明结合律。
证明:(待补)
设 \((a \oplus b) \oplus c\),我们设 \(d = a \oplus b\),我们知道,异或就是相同为 \(0\),不同为 \(1\),那么对于 d 二进制下的每一位就代表了 a 和 b 对应位的关系。假设 d 的这一位为 1,则说明 a 和 b 这一位一定一个 1 一个 0,
a ^ b = (~a & b) | (a & ~b)
数值转换
异或满足对于 \(a\oplus b=c\) 时,\(a\oplus c=b\),\(b\oplus c=a\)这两个式子同样成立,即等式两边可以交换。可以由自消的性质去搞出来。
不等关系
有一条,因为异或是不进位加法所以有 \(a \oplus b \le a + b\),所以合起来永远小于等于加起来。
异或操作本身可能会增加也可能减少,也是一种不稳定的操作。
一些思路
目前的异或题通常都是考异或本身的性质,而很少是转化成别的运算符,因为异或本身的性质很好,可以结合,交换,和加法很像,但是如果把异或转化成与、或的话,反而会变得很麻烦,因为一种操作符总归是要比多种要好得多。所以做题的时候不如去看看有什么性质。

浙公网安备 33010602011771号