【学习笔记】线性代数

1.【基本概念】

1.1【线性相关】

给定向量组 \(𝑣_1, 𝑣_2, …, 𝑣_𝑚\)

如果存在一组不全为 \(0\) 的系数 \(𝑎_1, 𝑎_2, …, 𝑎_𝑚\),使得 \(𝑎_1𝑣_1 + 𝑎_2𝑣_2 + … + 𝑎_𝑚𝑣_𝑚= 0\)

则称这组向量线性相关;否则称它们线性无关

直观地说,线性相关等价于其中某个向量可以由其余向量线性表示;线性无关则表示每个向量都提供了新的方向。

在模 \(2\) 意义下,系数只有 \(0, 1\),线性组合就是选出若干个数异或。

因此,一组数线性相关等价于存在一个非空子集的异或和为 \(0\)

1.2【基】

对于一组向量,取出其中一个极大线性无关子集,称为这组向量的一组

这里的“极大”是指:再加入原向量组中的任意一个向量都会变得线性相关。

基中的向量可以线性表示原向量组中的所有向量;反过来,基中的每个向量都不能由其余基向量表示。

任意两组基的大小相同,这个大小称为原向量组的,记作 \(rank\)

也就是说,秩表示这组向量中独立信息的个数。

若一个向量组有 \(𝑚\) 个向量、秩为 \(𝑟\),则其中恰好可以选出 \(𝑟\) 个线性无关向量;其余向量都能由这 \(𝑟\) 个向量线性表示。

2.【高斯消元】

2.1【普通高斯消元】

P2455 [SDOI2006] 线性方程组

int r,c;
for(r=1,c=1;c<=n;c++){
	int t=r;
	for(int i=r;i<=n;i++) if(fabs(mp[i][c])>fabs(mp[t][c])) t=i;
	if(fabs(mp[t][c])<eps) continue;
	for(int i=c;i<=n+1;i++) swap(mp[t][i],mp[r][i]);
	for(int i=n+1;i>=c;i--) mp[r][i]/=mp[r][c];
	for(int i=r+1;i<=n;i++)
		for(int j=n+1;j>=c;j--)
			mp[i][j]-=mp[i][c]*mp[r][j];
	r++;
}
if(r<=n){
	for(int i=r;i<=n;i++) if(fabs(mp[i][n+1])>eps) return 2;
	return 1;
}
for(int i=n;i>=1;i--){
	for(int j=i+1;j<=n;j++){
		mp[i][n+1]-=mp[i][j]*mp[j][n+1];
	}
}
return 0;

2.2【模意义下的高斯消元】

注意:模数不保证为质数时,非 \(0\) 元素未必有逆元,不能直接“除以主元”。

此时要利用辗转相除法,直到两个主元中一个数被消成 \(0\) 为止。

例如下面这个是 \(𝑖\) 为主元下标,欲消去第 \(𝑗\) 行的主元的示例:

int p = i, q = j;
while (a[p][i]) {
 ll u = a[q][i] / a[p][i];
 for (int k = i; k <= n; ++k) {
 a[q][k] = ((a[q][k] - u * a[p][k]) % MO + MO) % MO;
 }
 swap(p, q);
}
if (p == i) swap(a[i], a[j]);

用辗转相除法将每个方程化为 \(𝑎𝑥 ≡ 𝑏 (mod 𝑝)\) 的格式后,使用 exgcd 分别求解每个方程的解集即可。

2.3【有后效性dp】

主要是随机游走这些。

一般直接列出方程即可获得一个 \(𝑂(\)未知数个数\(^3)\) 的暴力做法。

一些较难的题目中方程式的形状有一些规律,进而要求用更优秀的复杂度消元。

3【线性基】

【学习笔记】线性基

4【行列式】

对于 \(𝑛 × 𝑛\) 矩阵 \(𝐴\),行列式定义为

\[det(𝐴) = \sum_{\sigma}(−1)^{𝑡(𝜎)} \Pi_{𝑖=1}^{n}𝐴[𝑖][𝜎(𝑖)] \]

其中 \(𝜎\) 枚举 \(1..𝑛\) 的所有排列,\(𝑡(𝜎)\) 为排列的逆序对数。

它本质上把所有“每行、每列各选一个元素”的乘积按排列奇偶性加减起来。

常用性质:

  1. \(det(𝐼) = 1\),且 \(det(𝐴𝐵) = det(𝐴) det(𝐵)\)

  2. 交换两行,行列式变号;一行乘以 \(𝑘\),行列式也乘以 \(𝑘\);一行加上另一行的若干倍,行列式不变。

  3. \(det(𝐴) ≠ 0\) 当且仅当 \(𝐴\) 满秩,当且仅当 \(𝐴\) 可逆。

int guess(){
	int res=1;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			while(mp[i][i]){
                mp[i][i]%=mod;
				int div=mp[j][i]/mp[i][i];
				for(int k=i;k<=n;k++){
					mp[j][k]-=div*mp[i][k]%mod;
                    mp[j][k]%=mod;
				}
				swap(mp[i],mp[j]);
				res=-res;
			}
			swap(mp[i],mp[j]);res=-res;
		}
	}
	for(int i=1;i<=n;i++){
		res*=mp[i][i];
		res=(res%mod+mod)%mod;
	}
	return res;
}

4.1【LGV引理】

除了LGV引理之外,行列式几乎没什么应用

给定有向无环图,以及一个起点集合 \(𝐴\) 和一个终点集合 \(𝐵\),两者大小都为 \(𝑚\)

对于长度为 \(𝑚\) 的排列 \(𝜎\),设 \(𝑓(𝜎)\) 表示点不相交的 \(𝑚\) 条路径形成的路径组数量,其中第 \(𝑖\) 条路径起点为 \(𝐴[𝑖]\),终点为 \(𝐵[𝜎(𝑖)]\)

\(𝑡(𝜎)\) 表示 \(𝜎\) 的逆序对数量。

构造 \(𝑚 × 𝑚\) 的矩阵 \(𝑀\) 使得 \(𝑀[𝑖][𝑗]\)\(𝐴[𝑖]\)\(𝐵[𝑗]\) 的路径条数。

\(det(𝑀) = \sum_{\sigma}(−1)^{t(𝜎)}𝑓(𝜎)\)

特别的,LGV 还可以拓展到边有边权的版本,这时把 \(𝑀[𝑖][𝑗]\)路径条数 改为 \(\sum{路径}\) 该路径上边的边权乘积 即可。

非常非常好的证明

大概意思就是不合法的路径之间互为对偶,对偶容斥去除非法贡献就是行列式的形式

posted @ 2026-08-21 16:21  Aistyr  阅读(7)  评论(0)    收藏  举报