[笔记]线性基
线性基的定义:若干 \(0, 1\) 向量的集合 \(s\),使得 \(\forall \overrightarrow{v} \in s\),不存在 \(p_1, p_2 \cdots p_k(\overrightarrow{v_{p_i}} \ne \overrightarrow{v})\),使得 \(\oplus_{1 \le i \le k}\overrightarrow{v_{p_i}} = \overrightarrow v\)。
线性基可以类比于平面向量中的基底。类比向量,线性基中的向量也可以说他们线性无关。
- 怎么求线性基
将线性基们排成矩阵。对矩阵做初等行列变换后得到的仍然是一组线性基。
因此可以将所有初始向量扔到矩阵里,然后进行初等行列变换削成下三角矩阵。根据高斯消元的过程可以发现,线性基的最高位 \(1\) 位置互不相同。因此最后消到为 \(0\) 的时候,前面 \(> 0\) 的就是线性基。
由此也可以发现线性基大小不超过 \(\log w\)。
这个玩意有两种写法。第一种是用上面初等行列变换的思路:
rep(i, 1, n) {
rep(j, i + 1, n)
if (a[j] > a[i]) swap(a[i], a[j]);
if (!a[i]) break;
dep(j, 63, 0) if ((a[i] >> j) & 1) {
rep(k, 1, n) if (k != i and ((a[k] >> j) & 1))
a[k] ^= a[i];
break;
} Base.push_back(a[i]);
}
第二种是基于插入的实现:
auto ins = [&](int x) {
for (auto i : Base) x = min(x, i ^ x);
if (x) Base.push_back(x);
};
rep(i, 1, n) ins(a[i]);
我个人偏向于前一种写法,因为它快得多。