线性基小结

线性基是用来处理异或和的一大利器,对于一个数集\(S\),它的线性基是一个最小的集合\(S_1\),使得\(S\)内元素异或得到的值的值域与\(S_1\)内元素的值的异或得到的值的值域相同

很明显一个序列的线性基具有如下的性质:集合内元素相互异或得到的值不可能为0

证明:反证法,假设存在\(a_1,a_2,\cdots,a_p\)使得\(a1\ xor\ a2\ xor \cdots \ xor\ a_p=0\)

​ 由异或的性质就可以得到\(a_1=a_2\ xor \cdots \ xor \ a_p\)

​ 对于某一个数\(x=a_1 \ xor\ y\),如果\(y\)能被该线性基用异或表示,那么将\(a_1\)\(y\)异或在一起来表示\(x\)的话,无论怎么样都不会用到\(a_1\)

​ 即存在一个更小的线性基\([a_2,a_3,\cdots,a_n]\)\(a_1\)是无用的,这与线性基的定义相矛盾,原命题得证

由上面的性质你可以得到如下推论:如果某个数\(x\)可以被这个线性基表示出来,那么这个表达方式唯一(证明也可以使用反证法)

构造

对于一个给定的序列,如何构造它的线性基呢?

我们记原来的序列为\(a_1,a_2,\cdots,a_n\),它的线性基为\(p_1,p_2,\cdots,p_m\)(其中\(m\)\(a_i\)中的数在二进制表示下的最大位数)

同时我们规定,\(p_i\)的二进制表示中最高位是第\(i\)位且这一位为1

也就是说,对于一个\(p_i\)只会有

​ 1)若\(p_i=0\),则只有可能在满足\(j>i\)\(p_j\)的二进制表示的第\(i\)上出现1

​ 2)若\(p_i\not=0\),那么\(p_i\)中比第\(i\)位更高的位上一定是0,但比第\(i\)为更低的位上有可能出现1;并且对于所有的\(j>i\)\(p_j\)中的第\(i\)位上一定是0

流程的话我们考虑每一次\(insert\)一个数

假设当前\(insert\)的数是\(x\),我们从高位向低位枚举,如果当前\(x\)的最高位对应的线性基\(p_i\)为0,那么就令\(p_i=x\)并且结束;否则就令\(x=x\ xor \ p_i\)并且继续枚举

这样做显然不会破坏之前出现的值域,并且当我们考虑由这个数与其他数组成的新的异或值,由上面的操作我们知道\(x\)是可以被线性基中的某些数得到的,所以我也可以用这些数与其他数组合来得到新的异或值(即由操作过程我们是有\(x=p_{i_1}\ xor\ p_{i_2}\ xor \cdots xor\ p_{i_k}\)的)

合并

合并操作类似于插入操作,将线性基\(A\)中的所有元素依次插入线性基\(B\)中即可

查询

一般的查询就是询问一个数\(x\)能否被当前的线性基表示出来

这个问题与插入十分相似,对\(x\)的最高位逐步考虑即可

从线性基的最高位开始往下遍历,如果当前位\(L\)\(x\)的最高非0二进制位,则令\(x=x\ xor \ p_L\),一直到遍历完成,如果此时\(x\)为0则该数可以被表示出来,反之则不可(其实本质就是贪心,考虑必须要将当前的最高位消去即可证明)

应用

比较经典的就是查询某个数集内的最大(小)异或和

建出线性基之后考虑贪心,从高到低遍历线性基,如果当前取这一位对答案有贡献就取(可以从当前线性基的最高位对答案影响开始考虑,如果取当前的线性基的话,有构造可知对后续的线性基是否选取也会有影响)

最小异或和的话直接取最小的非\(0\)\(p_i\)即可(妈耶还是贪心

例题

Luogu3812 模板线性基

codeforces1101G. (Zero XOR Subset)-less

posted @ 2019-04-08 10:53  EncodeTalker  阅读(166)  评论(0编辑  收藏  举报