【基础操作】线性基详解
线性基是一个奇妙的集合(我摘的原话)
这里以非 $OI$ 的角度介绍了线性基
基础部分
模板题
给你 $n$ 个数的集合,让你选出任意多个不重复的数,使得它们的异或和最大。
线性基是什么
我们称集合 $B$ 是集合 $S$ 的线性基,当且仅当 集合 $B$ 和 集合 $S$ 的元素数相同,且集合 $B$ $=$ 集合 $S$ 能异或出的数的集合。
其中“能异或出的数的集合”表示从集合中选出任意多个数(不能不选),它们的异或和组成的集合。
怎么构造线性基
异或是基于二进制的,我们当然要以二进制位的角度考虑啦!
我们依次插入每个给定集合 $S$ 的数,设我们要往集合 $B$ 中插入一个集合 $S$ 的数 $x$,我们将 $x$ 从高往低位遍历二进制位。
设当前遍历到第 $i$ 位,
若遇到 $1$,则判断之前是否已插入过最高位为 $1$ 的数(设其为 $p_i$):
- 如果插入过,就把当前要插入的数异或上 $p_i$,再往低位遍历;
- 如果没插入过,就把当前插入的数赋给 $p_i$,退出。
可以通过数学归纳法(从 $p_i$ 和从高到低位消 $1$ 两个角度)证明,这样构造使 $p_i$ 的值的最高二进制位是第 $i$ 位(这一位当然就是 $1$ 了)。
对于“$p_i$ 的值的最高二进制位是第 $i$ 位”这部分,一开始 $p$ 数组都未被赋过值,满足定义;然后如果另一部分是正确的,那赋值之后 $p$ 数组依然满足定义。
对于“从高到低位消 $1$”这部分,如果另一部分是正确的,每次异或 $p_i$ 都不会对更高位造成影响(那些位还是 $0$),第 $i$ 位会被消成 $0$,所以只有更低位可能有 $1$,往下遍历就行了。
已经说过,一开始 $p$ 数组满足定义,所以第一部分正确,然后两部分互相归纳下去即可完成证明。
我们把这个数组 $p$ 称作“有序的”集合 $B$ 吧!(因为集合本身有无序性)
据说这种构造方式很像高斯消元?这个还不是,下文会说怎么构造才是。
这样构造的意义是什么
对于集合 $S$ 中的任意两个数 $x,y$,它们能异或出的三种数是(假设不能一个都不取,即不取空集)$x,y,x\bigoplus y$。
由于异或的偶数抵消(即偶数个相同的数相异或等于 $0$,比如 $x\bigoplus (x\bigoplus y) = y$)性质,我们可以把 $x$ 和 $y$ 的任意一个换成 $x\bigoplus y$,这两个数能异或出的三种数依然是 $x,y,x\bigoplus y$。
拓展:把两个 $S$ 的子集中的数任意互相异或,再把两个子集合并得到的子集 能异或出的数的集合 $B_1$ 与把任意互相异或之前的子集合并得到的子集 能异或出的数的集合 $B_2$ 相等。
重要结论:所以我们把原集合 $S$ 中的数任意互相异或,集合 $S$ 能异或出的数的集合 $B$ 不变。
由于我们构造线性基的方式中,每个 $p_i$ 都是原集合 $S$ 中若干个数的异或和,所以集合 $p$ 能异或出的数的集合 与原集合 $S$ 能异或出的数的集合相等。
那为什么要把要插入的数 $x$ 不断异或 $p_i$?
对于一个新插入线性基的数,根据前述构造方式,如果从高到低遍历完所有二进制位,都没能插入给一个 $p_i$,那这个数必定被异或成了 $0$。
证明:
- 从高到低遍历到第 $i$ 个二进制位时,只有当前要插入的数 $x$ 的第 $i$ 位为 $1$ 时才会考虑异或 $p_i$。
- $p_i$ 的值的最高二进制位就是第 $i$ 位(之前证明过),且这一位为 $1$。
结合这两条,我们发现,要插入的数 $x$ 一定会被从高到低位依次被异或成 $0$,而且已经遍历过的高位不会再被异或成 $1$。
在遍历最高位时,这个性质是成立的,而往低位遍历时,可以结合上述两条,用数学归纳法证明。
所以,遍历完所有位之后,如果 $x$ 还没被插入,就肯定被一堆 $p_i$ 异或成 $0$ 了。
这是什么意思呢?
说明 $x$ 一开始的值(就是在集合 $S$ 中的值)是能通过其它若干个数异或出来的(之前说过,$p_i$ 都是原集合 $S$ 的若干个数的异或和)。
那就已经能被表示了,所以不要它了。
综上,可以看出这个线性基最叼的地方是:它能把原集合构造成元素很少的新集合,使其能异或出的数的集合不变,且新集合能容纳一些特殊性质。
那模板题怎么做
我们发现,在线性基中,每种最高位的数只有一个(一个 $p_i$ 对应一个最高位)。构造完线性基后,我们从高往低再遍历一次二进制位,做贪心(因为高位的一个 $1$ 比低位的任意多个 $1$ 都大)。
具体地说,就是设当前最大值变量为 $ans$,初始时使 $ans$ 为 $0$,从高往低遍历到第 $i$ 位时,如果 $ans\bigoplus p_i\gt ans$,就更新 $ans$ 为 $ans\bigoplus p_i$。
证明:可以这样考虑,遍历到第 $i$ 位时,比第 $i$ 位高的位都已经极大,然后我们现在要确保第 $i$ 位极大。结合数学归纳法可知,高位优先大的贪心策略能保证答案最大。
拓展部分
请确保基础部分都会了再看这部分
首先说一个线性基特别重要的性质:一个线性基能异或出的每个数的组成方案是唯一的。换句话说就是对于一个线性基的任意两个不同的取数方案,异或出的数两两不相等。
原因很简单,根据之前说过的构造方法,如果新插入的一个数能被线性基中已有的数表示出来,那它在遍历完所有二进制位后也不会被插入,且它一定被若干个 $p_i$ 异或成 $0$。
由此可以推出 $2$ 个性质:
- 线性基能异或出的数一定不包括 $0$(包括 $0$ 说明线性基中有两个相等的数,其中一个就能被另一个表示了,不符合构造要求;而且线性基中每种最高位的数只能有一个,显然两个相等的数的最高位也是相等的,也不符合构造要求)
- 假设线性基中有 $cnt$ 个数,线性基能异或出的数的集合大小为 $2^{cnt}-1$($-1$ 就是去掉一个数都不取的情况)
(这些概念是给你深入学习用的,可能会有用)
模板题加强版
给你 $n$ 个数的集合,让你选出任意多个不重复的数,使得它们的异或和再异或一个常量 $s$ 最大。
题解
做之前的模板题时,我们让 $ans$ 一开始为 $0$。
这是为什么?
由于异或的性质,一个数异或 $0$ 等于这个数本身,所以我们可以把之前的模板题看做 要求若干个数的异或和再异或一个常量 $0$ 最大。
又因为异或有交换律,所以我们可以交换顺序,读作“要求一个常量 $0$ 异或若干个数的异或和最大”。
这道题同理。所以让 $ans$ 一开始为 $s$,再跟之前的模板题一样做最大值贪心就行了。
(这是我自己想出来的解释,好像没那么严谨)
XOR (HDU3949)
给你 $n$ 个数的集合,让你选出任意多个不重复的数(至少选一个),把它们的异或和放入一个新集合中(集合是有互异性的,相同的数只保留一个),求新集合的第 $k$ 小值。
简化题意:求线性基能异或出的数的集合的第 $k$ 小(其实某些情况下是 $k-1$,后面会说)。
题解
首先,对于这道题,线性基的构造方式就跟之前不太一样了,因为之前只要求最大,而现在要求第 $k$ 小。
但我们知道,线性基是以每个二进制为最高位存一个数的,那是不是容易想到把 $k$ 进制分解呢?
这样的话,在前文的构造方式的基础上,我们只需要改点限制:规定 $p_i$ 的值的最高位是第 $i$ 位,且在此基础上 $p_i$ 最小。
直接加了一个最小的限制,这怎么做?
考虑之前的 $p_i$,它除了在第 $i$ 位有个 $1$ 外,在更低的位还有若干个 $1$。
那我们是否可以用线性基中的某些数,尽量消去低位的那些 $1$?(我们知道,线性基中的数都是原集合 $S$ 的若干个数的异或和,线性基中两个数的异或和还是原集合 $S$ 的若干个数的异或和)
这个很好做,往线性基插入一个新数时,用这个 $p_i$ 更新 $p$ 数组的其它所有值就行了。
详细做法:
- 对于低位
现在插入的一个数放到了 $p_i$,它在一个更低的二进制位(设其为第 $j$ 位)上为 $1$,且 $p_j$ 已被赋过值,那就把 $p_i$ 更新为 $p_i\bigoplus p_j$。
证明:这种情况下让 $p_i$ 异或 $p_j$,不会对比第 $j$ 位更高的位造成影响,但会使 $p_i$ 的第 $j$ 位变成 $0$,这种情况下即使更低的位异或出再多的 $1$,这个数总体也变小了。
为了方便,从大到小枚举 $j$ 即可。
- 对于高位
只考虑低位显然不对,因为有可能 $p_i$ 的第 $j$ 个二进制位为 $1$,而 $p_j$ 此时可能没有值,但它以后被赋了值,这种情况下也应该用 $p_j$ 更新 $p_i$。
我们只能用赋值晚的更新赋值早的,所以对于插入的一个数 $p_i$,不仅要用更低位的 $p_j$ 更新它,还要用它更新更高位的 $p_j$。
这一部分依然从大到小枚举 $j$。
这样就把线性基中的所有数都互相更新成满足限制的最小值,具体见代码吧(反正很短)。
其实这才是线性基的通用构造方式(比如对于模板题,多出来的要求对答案没有影响,因此该构造方案可以兼容使用)。另外说一下,换个角度看这个构造方式,其实就是标准的高斯消元+矩阵消成三角形,文章开头给了个非 $OI$ 角度介绍线性基的链接,可以去那里看看矩阵高斯消元的讲解。那里所谓的把不在对角线上的 $1$ 能消掉就消掉,其实也就是让每行的数最小。异曲同工吧?
如上改变线性基的构造方式后,把 $k-1$ 二进制分解,若第 $i$ 位为 $1$ 就把 $ans$ 异或上 $p_i$。
证明比较冗杂(其实是不会表达),这里尽量短地说一下(其实还是很长):
你会发现,若 $p_i$ 的第 $j$ 个二进制位是 $1$,那 $p_j$ 一定没被赋过值(如果有值就能更新 $p_i$ 使其更小了)。
所以所有的 $p_i$ 在各自的位数范围内(就是不超过最高位)都必须且只能在某些相同的位上有 $1$。
比如线性基里的三个数(二进制表示)可能是这样的(高位自动补成 $0$,用于对齐,其实不用考虑):$$111\space\space 011\space\space 001$$
而不可能是这样的:$$111\space\space 010\space\space 001$$
因为最低位要么都是 $1$,要么都是 $0$(也就是说要么最低位的 $p_i$ 有值,要么没值,不能模棱两可)。
这样的话,有一个烦人的顾虑就没了。
这个顾虑我不知道怎么叫名字……
大概就是说,如果 $p_i$ 表示线性基中最高位二进制位为 $i$ 的数,我们知道第 $2^{i-1}$ 大异或和为 $p_i$,第 $2^{j-1}$ 大异或和为 $p_j$,但 $p_i\bigoplus p_j$ 不一定是第 $2^{i-1}+2^{j-1}$ 大异或和(如果直接是的话,证明早就结束了)。
因为两数异或后第 $i$ 到 $j-1$ 位的数是不用争议的达到最小了(因为只有 $p_i$ 有那些位),但第 $j$ 位及以后的位根本没有保证啊!
为了解决这些顾虑,我们拆开考虑:
对于第 $j$ 位,$p_i$ 的第 $j$ 位必定是 $0$,因为 $p_j$ 被赋过值。
对于更低的位,$p_i$ 和 $p_j$ 在那些位上的数完全相同,即一位要么都是 $1$,要么都是 $0$。
由于我们前面的新构造方式 是考虑把每个 $p_i$ 的 $1$ 消成 $0$,因此如果我们想得到其它的异或和,只能不消 $p_i$ 的 $1$,也就是把一些 $0$ 改回 $1$。
显然,只有 $p_i$ 为 $1$ 的位才有可能在与其它若干个 $p_j$ 异或后得 $1$(异或奇数次),而 $p_i$ 为 $0$ 的位在异或后,这一位肯定还是 $0$(因为异或的那些 $p_i$ 在同位也必须是 $0$)。
保留 $p_i$ 原有的 $1$,而再把 $0$ 改成 $1$,$p_i$ 在与其它若干个 $p_j$ 的异或和 只可能在把原异或和(就是把 $p_i$ 的 $0$ 改成 $1$ 之前与这些 $p_j$ 的异或和)的某些二进制位由 $0$ 变成 $1$,新的异或和显然不会变小。
所以顾虑就解决了, $p_i\bigoplus p_j$ 在第 $j$ 位及更低位的部分的数 已经达到最小,结合二进制原理可得 $p_i\bigoplus p_j$ 是第 $2^{i-1}+2^{j-1}$ 大异或和。
做完了?
然而这道题还有个比较坑的地方……
就是它要求至少选一个数,也就是不能不选(这种情况下异或和为 $0$),但你可以选出若干个数(至少一个)的异或和为 $0$(这种情况下 $0$ 才是最小的异或和),然而线性基中的数并不能异或出 $0$(因为任意两个数的最高位都不相同,至少最大的那个数的高位就消不掉),所以我们要特判能否异或出 $0$。
这个也很好判,回顾一下线性基的构造:你在往线性基中插数的时候,如果最终这个数没被插入,那它一定就被异或成 $0$ 了。这说明原集合 $S$ 的若干个数(至少一个)能异或出 $0$,这时把 $k$ 改为 $k-1$ 即可。
Xor(WC2011 / bzoj2115)
给定一个 $n(n\le 50000)$ 个点 $m(m\le 10000)$ 条边的无向图,每条边上有一个权值。请你求一条从 $1$ 到 $n$ 的路径,使得路径上的边的异或和最大。
路径可以重复经过某些点或边,当一条边在路径中出现了多次时,其权值在计算异或和时也要被计算相应多的次数。
注意:这条路径可以多次经过 $1$ 和 $n$,只要路径的第一个点是 $1$ 且最后一个点是 $n$ 即可。
可能有重边、自环。
题解
其实这题的重点是图论找性质……
如果路径不可以重复经过点边,那这就是我们常见的简单路径了,直着从起点连到终点的那一种。
如果路径可以重复经过点边,简单路径本身不会变(因为你肯定要从起点走到终点),变的只是可以多走一些环。
容易发现,一条可以重复经过点边的路径的异或和 相当于一条从起点到终点的简单路径的异或和 异或 若干个(可以是 $0$ 个)任意的环的异或和。
哪里来的若干个任意的环?
思考一下,从简单路径上的任意一点出发,到达一个环,跑一圈,再原路返回,从简单路径上的点到那个环的往返路径走了两次,异或和抵消为 $0$,因此实际上就多了一圈环的异或和。
那可不可以去跑一圈环套环(或者多个环套起来)呢?也是可以的。这样的话每个环依然都恰好被跑了一次,异或和就是 这些环上所有边权的异或和相异或。
由此也很容易看出,每个环至多只需要考虑跑一次(即算一次异或和)。因为跑偶数次的话,环的异或和会被抵消为 $0$,因此多就是算一次环的异或和,那跟跑一圈一样。
所以把图中的所有环提出来($DFS$ 根据生成树的返祖边找环),记下每个环上所有边权的异或和。
然后枚举每条简单路径,求出该简单路径的异或和(设其为 $s$),问题变成了找若干个环,使这些环的异或和相异或 再异或 $s$ 最大。这就是前文讲过的模板题加强版了。
这真的是很好的思维题啊!
Shallot(bzoj4184)
有一个一开始为空的集合,支持三种操作:加入一个数,删除一个数;每次完成前两种操作中的任意一个后,回答当前集合中若干个数的异或和最大是多少。
题解
动态线性基?麻麻我要离线
容易发现,线性基不支持删除……(想一想就知道了)
但可以离线,那线段树分治每个数出现的时间就行了(标记永久化),于是成了不用删除操作的裸题。
时间复杂度 $O(31\times n\times log(n))$。
albus就是要第一个出场
给定 $n(n\le 10000)$ 个数 $a_1, a_2, \ldots, a_n$,以及一个数 $Q$。将 $a_1, a_2, \ldots, a_n$ 的所有子集(可以为空)的异或值从小到大排序得到序列 $B$,请问 $Q$ 在 $B$ 中第一次出现的下标是多少?保证 $Q$ 在 $B$ 中出现。
题解
我靠结论题
我当我在学习
这题最关键的问题就是异或和不去重!
我们知道,线性基每种选数方案的异或和是互不相同的(前文证明过该结论)。
那我们考虑一下每个数出现了多少次。
不难想到,线性基里的数很少,那没插入线性基的那些数是怎么着来着?
没错,就是被线性基中若干个数异或成 $0$ 后扔掉了。也就是那些数已经能被线性基中的数异或出来了。
如果我们不扔掉这些数,把这些 $0$ 也插入线性基,那异或和会是什么情况?
就是随便用这些 $0$!
假设原集合给了 $n$ 个数,线性基大小为 $|B|$,那剩下的 $n-|B|$ 个数肯定就是这些 $0$ 了。
在放入这些 $0$ 之前,线性基的每种选数方案异或出了一个唯一的异或和(也就是只有这一种方案得到这个异或和),现在多了 $n-|B|$ 个 $0$,而每个 $0$ 都可以用或不用,总共就有 $2^{n-|B|}$ 种方案得到这个异或和。
之前讲过了求第 $k$ 小的方法,现在我们要找比一个数 $Q$ 小的异或和的数量,本来是二分,但由于是在二进制位上做,所以可以优化为 只要在原线性基中枚举每个 $p_i$,尝试一下把 $sum$ 异或上 $p_i$ 是否小于 $Q$,如果小于就异或上这个数就行了,顺便加上比这个数小的数的数量(就是 $2^i$)。最后别忘了答案 $+1$(因为问的是 $Q$ 本身的出现位置,要算上自己的排名,刚才统计的只是比它小的数的数量)。
做完这道题后才发现,原来随便给一堆数,每个能异或出的数的出现次数都相同?我fo啦……
后记
1. 线性基不资瓷删除
2. 线性基大小为所有数的最大二进制位数(这不是废话么)
3. 线性基(大概)不资瓷限定选数的数量
4. 怎么什么数学内容都能硬套到 $OI$ 中……
在美妙的数学王国中畅游