以下定义\(xor(a_1)=a_1,xor(a_1,\dots a_{n-1},a_n)=xor(a_1,\dots,a_{n-1})\oplus a_n\),其中\(\oplus\)为按位异或
线性基是指\(n\)(\(n\geq 2\))个数\(a_1\dots a_i\dots a_n\)中任意取出\(x\)(\(1\leq x\leq n\))个数进行\(xor\)操作所能得到的值组成的集合的一组基。
思考
思考1
注意到一个性质:\(a_1,a_2,\dots,a_i,\dots,a_n\)进行xor所能得到的数的集合与\(a_1,a_2\oplus a_1,\dots,a_i\oplus a_1,\dots,a_n\oplus a_1\)进行xor所能得到的数的集合是相同的。
进一步,\(a_1,a_2\oplus a_i\oplus a_j\oplus\dots,\dots\)也是与原序列相同的。
思考2
另外一个问题是一个\(w\)位的二进制数\(a\)和一个\(w+1\)位的二进制数\(b\)进行异或,结果一定是\(w+1\)位的。(我们说一个二进制数是\(w\)位的,当且仅当它大于等于\(2^{w-1}\)小于\(2^w\))因为在第\(w+1\)位上,\(a\)是\(0\)而\(b\)是\(1\),所以结果里这一位是\(1\)。
同理,一个\(w\)位的数与一个\(w'\)(\(w'>w\))位的数异或,结果就会是\(w'\)位的。反过来也成立,就是一个\(w\)位的数与一个\(w'\)(\(w'
什么意思呢?就是说两个位数不一样的二进制数相异或,结果的位数取较大的那一个。
现在考虑位数都是\(w\)的两个数异或。因为他们的第\(w\)位都是\(1\),所以结果的第\(w\)位是\(0\)。而\(w\)位以上的显然都是\(0\),\(0\)又不能做最高位,所以位数会减少。
思考3
还有一点是说xor运算时各个二进制位之间是独立的。那么现在不妨考虑只有一位的情况。
如果只有0,0=0,0$\oplus$0=0,只能得到0。
- 如果只有1,那么1=1,1$\oplus\(1=0,1\)\oplus\(1\)\oplus$1=1,即偶数个1得0,奇数个1得1。
如果0和1都有,那么显然0和1都能得到。
思考4
考虑在二进制下 \(a>b\) 的条件。
如果 \(a\) 的位数比 \(b\) 大,那么显然\(a>b\)。
否则当 \(a\) 和 \(b\) 位数相同时,那么应该按照字典序来,即从高位到低位,如果在这一位上 \(a\) 和 \(b\) 不同,那么这一位上较大的那一个数大。
线性基 \(\rightarrow\) 集合
首先注意到如果直接把原序列作为线性基,是完全符合条件的。
其次注意到这个序列里其实有很多无用的数,也就是可以被其他数xor得到。
于是不难想到一个做法:维护一个集合,依次插入原序列的数,如果发现当前要插入的数可以用集合内的数xor得到,那就不插入。
瓶颈
这个做法的瓶颈在于如何判断一个数是否可以用集合内的数xor得到。
好像没有什么比较优秀的解决方案。
如果这个数等于0,那么不用做。(随便取一个\(x\),然后\(x\oplus x=0\))
然后,你可以考虑把这个数与集合里的某个数\(t\)相异或,然后递归判断结果。
但是问题在于,与哪个数异或呢?
弱化(假的)
不妨考虑一个特殊情况:现有集合内的数的二进制位数各不相同。
现在要新加入一个\(w\)位的数\(x\)。
如果集合里没有\(w\)位的数,那么根据思考2,现有的数不可能xor出\(x\)。(因为集合内的数的位数两两不同,而\(w_1\)位的数与\(w_2\)位的数异或得到的数只能是\(w_1\)或\(w_2\),不会出现\(w\))
如果集合里有\(w\)位的数,考虑上面提到的做法,即与集合内的某个\(w'\)位的数\(x'\)相异或,然后递归判结果。
- 如果\(w'>w\),那么结果将是一个\(w'\)位的数,而此时集合内除了\(x'\)没有其他\(w'\)位的数了。这时只会变成第一种情况,显然不可行。
- 如果\(w'
,那么结果还是一个\(w\)位的数,如果一直这样做下去,显然没有任何用处,不可行。 - 所以只能\(w'=w\)。那么根据思考2,位数只会越减越小,最终变成可插入的数或者0。
综上,检查有没有\(w\)位的数,如果没有就说明不能xor出来;否则就把它异或上原有的一个\(w\)位的数,递归判断结果;递归到这个数等于\(0\),判断为这个数能xor出来。
正确性参照上文推理。
“强制弱化”?
很有意思的是,既然我们发现如果集合内的数的二进制位数各不相同时很好做,那么我们为何不想办法让它正好满足这个性质呢?
根据思考1,插入\(x\)和插入\(x\oplus a_i\oplus a_j\oplus\cdots\)是等价的。
注意到我们认为能插入一个数\(x\),是在判断\(x\)或者\(x\)异或原有的数若干次之后,集合内没有与\(x\)位数相同的数时进行的。
结合以上两点,我们完全可以在判断可以插入时,直接将当前的数(也就是\(x\)异或了若干个集合内原有的数之后的数)插入集合。此时因为我们是判断当前的数在集合里没有相同位数的才插进去的,正好可以保证集合内的数的位数两两不同。