线性基
看了好多博客,,,,
线性基是一组数,是一个集合的产物,一般用来求原集合子集异或和极值的问题。
有什么作用?
通过线性基中元素xor出的数的值域与原来的数xor出数的值域相同。
但同时它这组数的大小只有原集合最大数的二进制位那麽多 (60 多位),
线性基与原集合关于异或作用一样,但是他是最简的,好像线性代数里面叫做 基。
构造
求线性基时将一个数的二进制位看成一个向量。假定原集合为 a a a 数组,线性基为 p p p 数组。
对于每个 a [ i ] a[i] a[i],按二进制从高位到低位扫,找最高位的 1,假如 a [ i ] a[i] a[i] 的第 j j j 位是最高位的 1。 p [ j ] p[j] p[j]为 0 的话,即不存在,直接插入 p [ j ] = a [ i ] p[j] = a[i] p[j]=a[i];否则将 a [ i ] a[i] a[i] ^= p [ j ] p[j] p[j],继续扫 a [ i ] a[i] a[i] 剩下的位。
其实相当于不断的将 a [ i ] a[i] a[i] 插入线性基,同时保持线性基的性质(线性无关)。
const int base = 60; // 一般long long 也就18位,即 60 多位二进制
int a[N], p[base+3];
for(int i = 0; i < n; i++){ // 对于每个数 a[i]
for (int j = base; j >= 0; j--){ // 从高位到低位找 a[i] 最高位 1 的位置
if(a[i] >> j & 1) // 跳过前导 0
if(!p[j]){ // 该行没数,直接填
p[j] = a[i];
break; // 填完跳出
}else{
a[i] ^= p[j]; // 该行有数,异或之后继续看 a[i] 低位
}
}
}
性质
- 线性基中的每个向量的二进制最高位均不同,并且,我们称二进制最高位为第 i 位的元素称为“线性基的第 i 位”。
- 原集合 a a a 所在线性空间中每个元素都有唯一的方案由线性基中元素异或得到。
这样我们得到的
p
p
p 数组是一个上三角矩阵,而且元素全都是 0, 1。
类似于这样:
10010
01001
00100
00000
00001
可以知道线性基有多少组非零向量。
进一步简化 p p p 数组可以得到很多信息。下面两种方式将 p p p 数组化为对角矩阵。
-
for(int i = 0; i < n; i++){ // 对于每个数 a[i] for (int j = base; j >= 0; j--){ // 从高位到低位找 a[i] 的第一个不为 0 的数的位置 if(a[i] >> j == 0) continue; // 跳过前导 0 if(!p[j]){ // 该行没数,直接填 p[j] = a[i]; for (int k = j - 1; k >= 0; k--) // 使第 p[j] 只有第 j 位为 1 if(p[k] && p[j]>>k&1) p[j] ^= p[k]; // 下面的行消自己 for (int k = j + 1; k <= base; k++) if(p[k] >> j&1) p[k] ^= p[j]; // 自己消上面的行 break; }else{ a[i] ^= p[j]; // 该行有数 } } }
-
for(int i = base; i >= 0; i--){ if(!p[i]) continue; for (int j = i + 1; j < base; j++){ if(p[j]>>i&1) p[j] ^= p[i]; } }
得到对角矩阵之后可以算第 k k k 小。
// 求线性基时加上
for (int i = 0; i <= base; i++){ // 后面查询用到,存非零位
if(p[i]){
v.push_back(p[i]);
}
}
ll ask(ll x){ // 查询第 k 小
if(v.size() != n) // 线性有关,可以异或出来 0
x--;
if(!x)
return 0; // 第一小的数是 0
if(x >= (1LL << v.size())) // x 超出所有能得到的值数量的范围
return -1;
// 能得到 0,x 已经 -1了,x 最多达到2^v.size()-1;
// 不等得到 0,x 最多达到v.size()-1
ll ans = 0;
for(int i = 0; i <= base; i++){ // 将第 i 为异或起来
if(x >> i&1){ // 第 i 位为 1
ans ^= v[i];
}
}
return ans;
}
参考
https://blog.sengxian.com/algorithms/linear-basis
https://blog.csdn.net/Cassie_zkq/article/details/95396029
https://www.cnblogs.com/vb4896/p/6149022.html
https://blog.csdn.net/qq_41286356/article/details/94839220
https://ouuan.github.io/线性基学习笔记/
https://blog.csdn.net/litble/article/details/78820648