线性基
【定义】
知识:向量组、线性空间、线性相关性。
-
向量组:一组向量,各个维数相等。
-
线性表示:如果一个向量能被一个向量组中若干个向量乘上系数后相加得到,称这个向量可被此向量组线性表示。
(例如向量组
, ,则 可被 线性表示) -
线性无关:设向量组
,如果 中任意一个向量都不能被 中其他向量线性表示,则称 是线性无关的。线性相关:向量组
不线性无关,就线性相关。 -
线性空间:记一个向量组
,任取 个系数 ,则 的 “生成子空间” 为 。说人话,用一个向量组能线性表示的所有向量,构成这个向量组的子空间。
而对于一个线性空间
可以看出,一组基可以理解为一个线性空间的简化表示。
【性质】
对于一个维度为
-
中任意 个向量构成的向量组必然线性相关。很好理解,类比有
个方程,必然有一个冗余。 -
中任意 个线性无关的向量是一组基。因为
个已经不符合线性无关的要求了,所以 个线性无关已经是极大的了。 -
若
中任意向量可被向量组 表示,则 是 的一组基。感性理解:
维向量,至少需要 个才能单独解开每一维,所以基至少需要 个向量;由上可知不可有 个向量。所以 个线性无关的向量必为基。 -
中任意取小于 个向量,一定可以再从 中选足够的向量,一起构成一组基。
【求法】
当给定一个向量组,想要求出它的子空间是很容易的:给每个向量乘一个系数加起来就行。
但是给定一个向量集合,求出它的基,貌似并不容易。
于是就产生了一个问题:给定一个线性空间,如何求出它的基?
(因为线性空间是无穷的,所以通过给出一个生成它的向量组表示)
【高斯消元】
考虑一下,线性基的本质就是去除了所有冗余向量。而这和消元有异曲同工之妙,我们可以使用高斯消元法来解。
要先保证高斯消元的操作:交换两行和消元是不会导致信息损失的,换而言之,交换两个向量的位置,和两个向量求和/差再替换,不会使线性空间变化。
而这是显然的,向量加减不会使线性空间变化,交换更不会。
下面进入正题。
先把向量组写成一个矩阵的形式,每一行代表一个向量,行数是向量组的大小。
对这个矩阵进行高斯消元,得到一个上三角矩阵:从左上角开始的一条斜对角线上都是
(不明白的回这里看)
其实这条对角线上有可能是
现在得到了一个上三角矩阵,这个矩阵的前
很巧妙吧?为什么呢?
设前
此时
【贪心法求解】
初始线性基为空,考虑在不断加入新元素的过程中维护线性基。
每加入一个向量
这里异或线性基和实数线性基有一点点不同。但都需要额外开一个数组
-
异或线性基。每加入一个数
,将其二进制分解从高位到低位扫。如果第 位是 ,看一下 是否存在:如果是,让 整个数异或上 ;否则,令 。这个过程感性理解,每找到一个数,就用之前确定的线性基尽可能从高到低消位。实在消不了了,才把消完的加入。
因为消完的前面一定是连续若干个位被线性基消了,而且至少消掉了原来(线性基个数)个位,所以这么做一直是线性无关的。
void insert(unsigned long long x) { for (int i = 63; ~i; --i) { if (!(x >> i)) continue; if (!b[i]) { b[i] = x; break; } x ^= b[i]; } }
-
实数线性基。
数组要记录高斯消元的对角线元素。每加入一个向量
,循环它的每一维。如果这一维 上不是零,用贡献了这一维 的向量把 的这一维消成零(注意同时 这一维后面的维度也可能被一起消掉),类似高斯消元。如果 这一维是 ,把现在剩下的 加入线性基。for (int i = 1; i <= n; ++i) { //插入 v[i] for (int j = 1; j <= m; ++j) { if (v[i].a[j] == 0) continue; if (b[j] == 0) { //当前线性基消不了 b[j] = i; //把剩下的v[i]加入 break; } double mul = v[i].a[j] / v[b[j]].a[j]; for (int k = j; k <= m; ++k) v[i].a[k] -= mul * v[b[j]].a[k]; //类高斯消元 } }
【复杂度】
【用途】
求出这个玩意,有什么用?
基很重要的一个性质,就是它能表示整个线性空间。而且它只有维度
一般初始给出的向量组会很多(一般
简化了向量组,无论是什么操作,都会好搞很多。
一个经典的例题:给定一些数,选若干个使异或和最大。
首先需要明确的一点是:异或可以看作不进位加法,它同时具有交换律和结合律,所以才能使用高斯消元搞线性基。不是什么向量运算都能搞线性基的。
把每一个数看作二进制数,每一位单独看作向量的一个维度,则题目可以看作
对这个向量求线性基。最后会剩下不到
求完线性基,现在就是求异或最大值了。由于
但是有上面的性质:除了对角线,其他都是
同时线性基还有一些同样经典的操作:
判断一个数是否能被异或出来:
求完线性基后把这个数做类似贪心法求解过程中的插入,如果这个数最后被消成
求异或第
求出线性基后,从高到低枚举每个线性基。因为线性基一定是对角线都是
当我们枚举到第
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!