线性基入门
线性基维护的是向量空间的一组基。在 OI 中,这种算法一般用来解决子集异或和类型的题目。
基本定义#
容易发现,异或运算本身等价于在各数位上进行模二意义下的加法。
即每一个数位看作一维,每一个数都看作一个 维向量。
我们相当于求 的一组基。
首先定义什么是线性表示:
定义1:定义一整数集合(以下均指整数集合) 的异或和 。
即为所有数异或起来的结果。
注意到这里的“系数”只有零和一,所以异或就是这个线性空间里唯一的线性运算。
定义2:定义一个集合 的张成 。
的所有子集的异或和组成的集合。与原本的张成定义类似。
若对于集合 ,,则称集合 线性相关。反正,则称 线性无关。
就是如果 中有一个元素 能被表示为其余某些元素的异或和,则这个集合 线性相关。
线性基#
我们称集合 是 的线性基,当且仅当 满足:
- 。
- 是满足条件 1 的最小集合。
通俗来讲就是没有冗余的向量组。
构造方法#
考虑高斯消元,显然可以直接求出基底。
高斯消元的过程相当于化成三角矩阵,那么我们只要类似的构造三角矩阵即可。
我们在进行高斯消元的时候,总是确定一个行向量,然后用其他行向量去减去这个行向量来进行加减消元。
那么我们这里就直接进行异或,把这一位异或掉即可。
具体来讲,我们定义数组 为集合 的线性基,其中 表示用来控制这一位为 1 的数。
考虑向 中加入一个数 。从高到低考虑 的二进制的每一个为 1 的数位:
- 如果 不存在,说明之前的数无法使这一位为 1,直接令 。
- 否则,对 进行消元,令 。
const int N = 105;
int n;
long long p[N], ans;
void ins(long long x) {
for (int i = 63; i>=0; i--) {
if (x >> i == 0) continue;
if (!p[i]) return p[i] = x, void();
x ^= p[i];
}
}
应用#
查询一个数是否可被表示#
与插入类似,直接进行消元,最终消成零就说明可被表示。
查询子集异或最大/小值#
逐位考虑即可。假设消元是从大到小进行的:
对于最小值,由构造方法知道, 即是可被表示的最高位为 1 的数。
找到存在的最低位的 ,容易知道这个数是唯一的。因为如果存在两个最高位都为 的数 ,那么 的最高位必定比 小,矛盾。
所以最小值就是这个 。
对于最大值,显然将所有存在的维度全部变成 1 是最大的。
查询第 小#
注意到我们在查询最小值的时候利用了最低位的唯一性。
那么我们能否对线性基进行一下改造,使得其具有类似的“唯一”性质呢?
注意到,如果只使用 这一类二的幂,是必定可以构造出一组基的,而且用这一组基来构造第 小的方法显而易见。
从高到低考虑每一位,将 异或上后面的某些 ,使得 只有最高位为一即可。
举例:
110 011 001
变成
100 010 001
然后就是简单的构造。
查询排名#
贰分。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现