线性基小记
Part 0:前置知识
线性空间是一个关于以下两个运算封闭的向量集合:
- 向量加法
。 - 标量乘法
。
给定一个向量集合
任意选出线性空间的若干个向量,如果其中存在一个向量能被其它向量表出,则称这些向量线性相关,否则称这些向量线性无关。
线性无关的生成子集被称为线性空间的基底,简称基。基的另一种定义是线性空间的极大线性无关子集。一个线性空间的所有基包含的向量个数都相等,这个数被称为向量空间的维数。
Part 1:OI 中的线性基
在 OI 中,线性基一般用于解决与异或有关的问题。
异或可以看作
规定:记
基的构建
从矩阵的角度理解,对于一个
现在给定二进制数集合
我们集合
市面上常见的线性基写法采用增量法,逐个加入向量,若能被之前的基表出则不加入。复杂度
struct Linear_Base
{
LL e[S];
Linear_Base(){memset(e,0,sizeof(e));}
void insert(LL x)
{
for(int i=61; i>=0; i--)
if(x&(1LL<<i))
{
if(e[i])
x^=e[i];
else
return e[i]=x,void();
}
}
}
张成空间判定问题
给出一个线性无关的二进制数集合
最大子集异或值
要求实现一个函数
从高位到低位考虑基,若异或后变大,则异或。
由贪心可证明正确性。
LL query(LL x)
{
for(int i=51; i>=0; i--)
if((x^e[i])>x)
x^=e[i];
return x;
}
小子集异或和
若原有的集合
反之,能得到
特判一下
将
void rebuild()
{
int tot=0;
for(int i=0; i<=61; i++)
{
if(!e[i])
continue;
for(int j=i-1; j>=0; j--)
if(e[i]&(1LL<<j))
e[i]^=e[j];
tmp[tot++]=e[i];
}
}
LL ask(LL k)
{
if(k>=(1LL<<cnt))
return -1;
LL res=0;
for(int i=cnt-1; i>=0; i--)
if(k&(1LL<<i))
res^=tmp[i];
return res;
}
线性基合并
由于线性基只有
例题
P3265 [JLOI2015] 装备购买
就是求一个价钱最小的极大线性无关子集。同 kruskal 一样按价钱从小到大加入,求解线性基即可。
P4301 [CQOI2013] 新Nim游戏
先手想要找到一个极大的集合,使后手面对这个集合时,无法找到一个子集满足异或和为
P3292 [SCOI2016] 幸运数字
对每个节点
P4839 P 哥的桶
使用线段树维护线性基合并。复杂度
CF895C Square Subsets
套路地想到质因数分解,指数全部
构建线性基,不在线性基里的数可以自由选择,所以答案为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?