====== 线性基 ======
===== 定义:=====
==== 张成: ====
* $T \subseteq S$,所有这样是子集$T$的异或和组成的集合称为$S$的**张成**记作$span(S)$。
==== 线性相关: ====
* 存在一个元素$S_j$可以用其它若干元素异或起来得到
* 或:存在一个子集的异或和为0
==== 线性基:====
=== 称$B$是$S$的线性基当且仅当: ===
- $S \subseteq span(B)$,即$S$是$B$的张成的子集。
- $B$是线性无关的。
=== 线性基的长度: ===
* 集合$B$中元素的个数
=== 线性基的基本性质: ===
- $B$是极小的满足线性基性质的集合,它的任何真子集都不可能是线性基;
- $S$中的任意元素都可以唯一表示为$B$中若干个元素异或起来的结果。
===== 构造:=====
线性基是动态构造的,我们只需要从空的$a$开始,每次考虑在一个已存在的线性基中插入一个数$t$即可。
==== 构造流程: ====
对于每个数$x$,从高位到低位扫描,扫到第$i$位为1时,若$a_i$上有数字$x=x \oplus a_i$,并向下继续扫,若没有数字$a_i=x$结束扫描。
inline void insert(ll x){
for(int i=50;i>=0;i--)if(x&(1ll<
==== 大致证明: ====
=== 未成功插入线性基: ===
考虑时候不能插入进去呢,显然就是它在尝试插入时异或若干个数之后变成了0 $\Rightarrow$ 新插入的数$x$可由当前的线性基异或表示 $\Rightarrow$ 所有数都能由当前的线性基异或表示。
=== 成功插入线性基: ===
假设$x$成功插入到了$a_i$,显然,它在插入前可能异或若干个数,那么就有:\\
$x \oplus a_j \oplus a_k \oplus ... = a_i$\\
即:$a_i \oplus a_j \oplus a_k \oplus ... = x$\\
$\Rightarrow$ 新插入的数x可由当前的线性基异或表示 $\Rightarrow$ 所有数都能由当前的线性基异或表示。
==== 性质: ====
构造出来的线性基满足:
- 若$a_i=0$:
* **只有**满足$j>i$的$a_j$的第i位才**可能**为1
- 若$a_i\ne0$:
* 整个$a$数组只有$a_i$的第$i$位二进制位1
* $a_i$的更高位($>i$的位数)**一定**为0
* $a_i$的更低位($
inline bool check(ll x){
for(int i=50;i>=0;i--)
if(x&(1ll<
==== 求数集能异或出的最大值: ====
使用贪心的思想:
inline ll getMax(){
ll ans=0;
for(int i=50;i>=0;i--)
ans=max(ans,ans^a[i]);
return ans;
}
**证明:**\\
$a_i$的第$i$位一定是1,而后面扫描到的$a_{i-1},a_{i-2},...,a_0$第$i$位一定不是1,而如果高位不是1低位再多1也弥补不了,所以当前只需要考虑第$i$位的情况,若$ans$的第$i$位为0异或后为1会变大就进行异或,若为1异或后为0会变小就不进行异或。
==== 求数集能异或出的最小值: ====
显然是最小的一个$a_i$,最小的%a_i%异或其它数字都会变大。
==== 求能异或出的第$k$小值: ====
从一个序列中取任意个元素进行异或,求能异或出的所有数字中第$k$小的那个。\\
首先对线性基进行改造,保证只有$a_i$的第$i$位是1,其它的第$i$位都为0。\\
改造方法是若$a_i$的第$j$位为1$(j
void init(){//处理线性基
for(int i=1;i<=50;i++)
for(int j=0;j>=1;
}
return ans;
}
**证明(或者说是理解):**其实处理完之后的线性基其实也还是原序列的一个线性基,回想上面的线性基处理过程,可以发现,处理完之后,线性基中的元素,作用其实都是提供自己最高位上的 1,那么只要使提供出来的 1 可以和 $k$的二进制的每一位上的 1对应,那么求出的$ans$一定就是第$k$小的。
===== 题目:=====
==== 洛谷4570 [BJWC2011]元素 ====
**题意:**给定一些矿石编号和矿石价值,问在保证矿石编号的任意子集的异或和不为0的情况下,最大价值是多少。\\
**题解:**很显然的贪心,按价值从大到小排序维护线性基。\\
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
\\
==== 洛谷3292 [SCOI2016]幸运数字 ====
**题意**:一棵树每个点上有权值,多次查询不同路径x->y的最大幸运值。幸运值:从x->y路径上的点选任意子集的异或和。\\
**题解**:倍增lca+线性基\\
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
\\
==== 洛谷3857 [TJOI2008]彩灯 ====
**题意:**每个开关可以控制一部分的灯,改变它们的开关状态,计算灯的状态有多少种可能。(对2008取模)灯的数量和开关的数量都小于50\\
**题解:**设线性基的长度为$x$,答案为$2^x$
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
\\
==== 洛谷4151 [WC2011]最大XOR和路径 ====
**题意:**给一个无向连通图,求一条从$1$到$n$的路径(可以不是简单路径),使经过的边权的异或和最大。\\
**题解:**首先注意到一个结论:对于所有的简单环,环上边权的异或和都可以无代价的获取。原因是可以从一号点出发进入该环绕一圈后原路返回。由于一条路径绕两边对答案的贡献为 $0$,所以这些简单环的异或和都可以无代价取得。那么现在问题就转化成了寻找一条 $1$到 $n$的路径,再异或上一些简单环的异或和,最大化答案。\\
我们考虑应该寻找哪一条路径:事实上任选一条路径即可。原因是选择的路径和答案路径一定可以构成一个环,所以异或上该环的权值就可以得到最优解。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
\\