求前 n 个自然数的异或值
时间复杂度 \(O(1)\) ,分为感性认识和理性认识。
如无特别注明,下文所指均为二进制下的数位。按位逻辑运算符号表在此处。
感性认识
由于 \(0\oplus 1=1\),问题也可以转化成求 \([1, n]\) 的异或值。
1 | Number Binary-Repr XOR-from-1-to-n |
所以我们可以这么写:
1 | // C++ program to find XOR of numbers |
理性认识
记 \(f(x,\ y)\) 为 \(x\) 到 \(y\) 的所有整数的异或值。
现在考虑 \(f(2^k,\ 2^{k+1}-1)\). 令 \(k\geq 1\),则 \(2^k\) 为偶数。且这里面的 \(2^k\) 个数从左往右第 \(k+1\) 位(最高位)都为 \(1\). 再结合异或运算法则我们就知道,将这 \(2^k\) 个数的最高位去掉,异或值不变。也就是说, \[ f(2^k,\ 2^{k+1} -1) = f(2^k - 2^k,\ 2^{k+1} -1 -2^k) = f(0,\ 2^k -1). \] 所以, \[ \begin{aligned} f(0,\ 2^{k+1} -1)&=f(0,\ 2^k -1)\oplus f(2^k,\ 2^{k+1} -1)\\ &=f(0,\ 2^k -1)\oplus f(0,\ 2^k -1)\\ &=0. \end{aligned} \] 也就是, \[ f(0,\ 2^k - 1) = 0\ (k >= 2). \]
对于 \(f(0,\ n)\ (n\geq 4)\) ,设 \(n\) 的最高位在第 \(k\) 位 \((k \geq 2)\). 则 \[ f(0,\ n) = f(0,\ 2^k - 1)\oplus f(2^k,\ n) = f(2^k,\ n). \] \([2^k,\ n]\) 共有 \(n+1-2^k\) 个数,设为 \(m\). 这些数的第 \(k\) 位(最高位)共有 \(m\) 个 \(1\).
(a) 当 \(n\) 为奇数时,\(m\) 为偶数,则最高位有偶数个 \(1\) ,所以 \[ f(0,\ n) = f(2^k,\ n) = f(0,\ n - 2^k). \] 且 \(n-2^k\) 与 \(n\) 同奇偶,我们可以递推: \[ f(0,\ n) = f(0,\ n - 2^k) = f(0,\ n - 2^k - 2^{k-1}) = \cdots = f(0,\ n \bmod 4). \] 注:\(n\geq4\). 每一步递推都将最高位去掉。
当 \(n \bmod 4= 1\) 时, \(f(0,\ n) = f(0,\ 1) = 1\).
当 \(n \bmod 4 = 3\) 时, \(f(0,\ n) = f(0,\ 3) = 0\).
(b) 当 \(n\) 为偶数时,\(m\) 为奇数,则最高位有奇数个 \(1\) ,所以 \[ f(0,\ n) = f(2^k,\ n) = f(0,\ n - 2^k) \vee 2^k. \] 注:最高位的 \(1\) 我们先提出来,最后用取或(\(\vee\))加回去。
像(a)那样递推时,我们会发现每一步都保留了当前最高位,所以除了 \(n\) 的最后两位其余都会被保留下来,我们记这个数为 \(n'\). \[ f(0,\ n) = f(2^k,\ n) = f(0,\ n \bmod 4) \vee n'. \]
当 \(n \bmod 4=0\) 时 \(n\) 的后两位是 \(00\),所以 \(n=n'\). \[ f(0,\ n) = f(0,\ n \bmod 4) \vee n' = f(0,\ 0) \vee n = n. \] 当 \(n \bmod 4 = 2\) 时 \(n=n'+2\),所以 \[ \begin{aligned} f(0,\ n) &= f(0,\ n \bmod 4) \vee n'\\ &=f(0,\ 2) \vee n'\\ &=3 \vee n'\\ &=3 \vee 2 \vee n\\ &=n+1. \end{aligned} \] 综上所述, \[ f\left( 0,\ n\right) =\left\{ \begin{array}{l} n&, n \bmod 4=0\\ 1&, n \bmod 4=1\\ n+1&, n \bmod 4=2\\ 0&, n \bmod 4=3. \end{array} \right. \] Q.E.D.