线性基小记

Part 0:前置知识

线性空间是一个关于以下两个运算封闭的向量集合:

  • 向量加法 a+b
  • 标量乘法 ka

给定一个向量集合 A={a1,a2,,ak},若向量 b 能由 a1,a2,,ak 经过向量加法和标量乘法运算得出,则称向量 b 能被向量 a1,a2,,ak 表出a1,a2,,ak 能表出的所有向量构成一个线性空间,称作 A张成空间,记作 span(A)A 被称作这个线性空间的生成子集

任意选出线性空间的若干个向量,如果其中存在一个向量能被其它向量表出,则称这些向量线性相关,否则称这些向量线性无关

线性无关的生成子集被称为线性空间的基底,简称。基的另一种定义是线性空间的极大线性无关子集。一个线性空间的所有基包含的向量个数都相等,这个数被称为向量空间的维数


Part 1:OI 中的线性基

在 OI 中,线性基一般用于解决与异或有关的问题。

异或可以看作 mod2 意义下的向量加法。因此不难直接将原有的定义推广到异或上。

规定:记 k 为二进制位长,cnt 为线性基中基底的个数。

基的构建

从矩阵的角度理解,对于一个 n×m 的矩阵,把每一行看作长度为 m 的行向量。将矩阵看作“系数矩阵”进行高斯消元,得到一个简化阶梯形矩阵。显然,简化阶梯形矩阵的所有非零行向量线性无关。而消元过程又不改变行向量的张成空间。于是,简化阶梯形矩阵的所有非零行向量就是该线性空间的一个基。

现在给定二进制数集合 V,求 span(V) 的一组解。

我们集合 V 写成一个 |V|k 列的 01 矩阵,高斯消元即可。

市面上常见的线性基写法采用增量法,逐个加入向量,若能被之前的基表出则不加入。复杂度 O(|V|k)。(其实本质上一样)。

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();
			}
	}
}

张成空间判定问题

给出一个线性无关的二进制数集合 B,询问 a 是否在 span(B) 中。

aspan(B) 等价于 a,B 线性相关。类似基的构建一样将 a,B 放在一起消元即可判断。

最大子集异或值

P3812 【模板】线性基 - 洛谷

要求实现一个函数 query(x),表示查询 x 与线性基的最大异或和。那么最大子集异或值就是 query(0)

从高位到低位考虑基,若异或后变大,则异或。

由贪心可证明正确性。

LL query(LL x)
{
	for(int i=51; i>=0; i--)
		if((x^e[i])>x)
			x^=e[i];
	return x;
}

k 小子集异或和

若原有的集合 V 是线性无关的,则异或不到 0,能得到异或值的个数是 2cnt1 。(有时允许选空集则无需考虑)。

反之,能得到 0,则为 2cnt 个。

特判一下 0,然后重构线性基,将三角基消成对角基,即令 ei0i1,i+1k1 都为 0。并从小到大排序记为 b0,b1,,bcnt

k 按二进制展开,若第 i 位为 1,则答案异或上 bi。证明同按位贪心。

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;
}

线性基合并

由于线性基只有 O(k) 个元素,所以暴力插入即可,时间复杂度 O(k2)

例题

P3265 [JLOI2015] 装备购买

就是求一个价钱最小的极大线性无关子集。同 kruskal 一样按价钱从小到大加入,求解线性基即可。

P4301 [CQOI2013] 新Nim游戏

先手想要找到一个极大的集合,使后手面对这个集合时,无法找到一个子集满足异或和为 0。因此,这个集合一定是线性无关的 。

P3292 [SCOI2016] 幸运数字

对每个节点 x 维护 gx,i 表示从 x 向上走 2i 步所到达的所有节点(不包括 x)的线性基。由于可重复贡献直接树上 RMQ 即可。

P4839 P 哥的桶

使用线段树维护线性基合并。复杂度 O(nlognlog2V)

CF895C Square Subsets

套路地想到质因数分解,指数全部 mod2,因为 ai70,于是将每个数用它的质因子指数的二进制表示。那么成绩操作相当于异或操作,即问有多少个子集异或和为 0

构建线性基,不在线性基里的数可以自由选择,所以答案为 2n|V|1

posted @   xishanmeigao  阅读(47)  评论(0编辑  收藏  举报
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示