【小结】线性代数

置顶

题单在这。

矩阵

矩阵:由 \(m\times n\) 个数排成的 \(m\)\(n\) 列的数表,记作 \(A_{m\times n}\),其中第 \(i\) 行第 \(j\) 列元素记作 \(A_{i,j}\)

方阵:行数列数相等的矩阵。

零矩阵:所有元素均为 \(0\) 的矩阵,记为 \(O\)

单位矩阵:主对角线元素为 \(1\),其余元素为 \(0\) 的方阵,记为 \(I\)

对于任意方阵 \(A\)\(A\times I=I\times A=A\)

矩阵加法:\((A+B)_{i,j}=A_{i,j}+B_{i,j}\)

矩阵数乘:\((kA)_{i,j}=k\times A_{i,j}\)

矩阵乘法:

\(A\)\(m\times p\) 矩阵,\(B\)\(p\times n\) 矩阵,则他们的乘积 \(C=A\times B\) 是一个 \(m\times n\) 矩阵,其中:

\(C_{i,j}=\sum_{k=1}^{p} A_{i,k}\times B_{k,j}\)

结果矩阵的第 \(i\) 行第 \(j\) 列元素,等于 \(A\) 的第 \(i\) 行与 \(B\) 的第 \(j\) 列对应元素乘积之和。

性质:

  1. 有结合律

  2. 无交换律。

矩阵乘法优化 DP

\(f_i=f_{i-1}+f_{i-2}\) 为例。

注意到仅与相邻 \(2\) 项有关,那么构建一个 \(2\times 2\) 的矩阵。

一开始向量是 \((1,1)\)。竖着的。

那么考虑如何构建一个矩阵 \(A\),使得 \(A\times(f_{i-1},f_{i-2})\to (f_i,f_{i-1})\)

那么这个矩阵可以是:

\(11\)

\(10\)

然后因为有结合律,所以可以快速幂维护矩阵乘法。

具体矩阵快速幂的结构体写法:

struct Matrix
{
	int n,m;
	vector<vector<int> > a;
	Matrix(int nn,int mm):n(nn),m(mm),a(nn,vector<int>(mm,0)){}
	Matrix operator*(const Matrix &b)const
	{
		Matrix res(n,b.m);
		int i,j,k;
		for (i=0;i<n;i++)
		{
			for (k=0;k<m;k++)
			{
				if (!a[i][k]) continue;
				for (j=0;j<b.m;j++) res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
			}
		}
		return res;
	}
};
Matrix qp(Matrix a,int b)
{
	Matrix res(m,m);
	for (i=0;i<m;i++) res.a[i][i]=1;
	while (b)
	{
		if (b&1) res=res*a;
		a=a*a;
		b>>=1;
	}
	return res;
}

然后对于很多 DP,只与前面几项有关,那就可以用矩阵加速。

还有一种题,就是最短路路径长度固定。求方案数。这种问题可以用快速幂倍增,然后根据结合律,每次都可以跑 floyd。这就相当于 \(d\) 次 floyd。

高斯消元

高斯消元是解 \(n\) 元一次方程组的一个算法。

\(n\) 元一次线性方程组:

\(a_{11}x_1+a_{12}x_2+\dots+a_{1n}x_n=b_1\)

\(\dots\)

\(a_{n1}x_1+a_{n2}x_2+\dots+a_{nn}x_n=b_n\)

现在有一个定义,是增广矩阵,对于如上的方程,定义如下:

\(a_{11} a_{12} \dots a_{1n} b_1\)

\(a_{21} a_{22} \dots a_{2n} b_2\)

\(\dots\)

\(a_{n1} a_{n2} \dots a_{nn} b_n\)

高斯消元的本质是对增广矩阵做不改变方程组解的变换,这就是初等行变换,共有 \(3\) 种:

  1. 交换 \(2\)

  2. 把某行的数乘一个非零常数 \(k\)

  3. 把某行乘 \(k\) 倍加至另一行

阶梯形矩阵:

高斯消元的目标就是将增广矩阵转化为三角阶梯形矩阵:

\(a_{11} a_{12} \dots a_{1n} b_1\)

\(0a_{22}\dots a_{2n} b_2\)

\(00a_{33}\dots a_{3n} b_3\)

\(\dots\)

\(000000\dots a_{nn}b_n\)

然后就可以通过从后往前计算 \(x_{n\sim 1}\) 然后回代算出答案。

矩阵的秩:

将矩阵转化为阶梯矩阵后,非零行的数量称之为矩阵的行秩。

矩阵的列秩同理。行秩=列秩。统称为矩阵的秩。

线性方程组解的分布:

对于 \(n\) 个未知数,\(m\) 个方程构成的线性方程组,其增广矩阵为 \(m\)\(n+1\) 列,利用初等行变换,化简为阶梯矩阵,设矩阵的秩为 \(R\)

情况 \(1\):无解

系数矩阵的秩<增广矩阵的秩

情况 \(2\):无数解

增广矩阵的秩<n

情况 \(3\):唯一解

系数矩阵的秩=增广矩阵的秩=n

高斯消元的原理:前向消元(化为三角矩阵)+回代求解

  1. 选主元(数学可以任意选一个主元,但在信息中选绝对值最大的减小精度误差)设主元是 \(a_{ii}\),那么对于下面的,要消元,令 \(k=a_{ji}/a_{ii}\),然后第 \(j\) 行减去第 \(i\) 行乘 \(k\),这样就消掉了。这就是对于每一列 \(i\),消去 \([i+1,n]\)

  2. 回代 一步步倒着回代即可。

高斯-约旦消元法:

变成最简行阶梯矩阵可以不用回代。

每次在第 \(i\) 列确定最大系数 \(a_{ii}\) 后,将第 \(i\) 行同时除以 \(a_{ii}\),这样 \(a_{ii}\) 就变成了 \(1\)。然后第 \(i\) 列所有元素也可以通过同样的消元变成 \(0\)。最后 \(x_i=a_{i,n+1}\)

一般都是用这种算法因为更好写。

时间复杂度:\(\mathcal O(n^3)\)

注意:先判无解,后判无数解。

但是注意:这一个东西是有问题的。在高斯消元的模板中体现不出来,但是在 P2455 能体现出来。

HACK:

4

0 0 2 1 2

0 0 0 1 1

0 0 0 0 0

0 0 1 1 1

OUTPUT:

-1

WRONG OUTPUT:

0

我们惊奇的发现这个数据很 6,它看似无数解实则无解。来看看为啥。

首先第 \(1\) 列我们会跳过。然后第 \(2\) 列我们也会跳过。但是第 \(3\) 列我们还是会跳过。因为找不到主元。

但是这一步是错误的。为啥捏?

因为主元不在下面,而是在上面。

所以如果上面的那个没有被当做过主元,可以当这个的主元。

这下,高斯消元的代码就彻底正确了。可以解决一些题目了。

模板代码看 P2455 不要看高斯消元板子。

线性基

问题:求一组数的最大异或和。

发现难点在于这组数的数量太多。考虑能不能用很少的数代替这个很长的序列。

首先定义一个东西。

线性有关:存在一组数 \(s_1,s_2,\dots,s_n\) 满足 \(s_1a_1\oplus s_2a_2\oplus \dots \oplus s_na_n=0\)

线性无关:不存在上述数组。

那我们考虑如果这个线性基线性有关的话那就很浪费。

我们现在需要找出最短的,和原序列本质相同的一个序列。这玩意就叫线性基。

但其实线性基不只能搞异或的问题,其他问题有些可以结合高斯消元。

但先考虑异或。

\(p_i\) 表示二进制下最高位在 \(2^i\) 的基。

那输入 \(n\) 个数,依次插入。设目前插入的值是 \(x\)

遍历 \(i=63\sim 1\)。如果 \(p_i\) 上没有值,那直接填上。结束。

如果 \(p_i\) 有值,那就让 \(x\oplus p_i\to x\)。然后继续做。容易发现 \(a,b\)\(a,a\oplus b\) 是本质相同的。能异或出的值都是 \(a,b,a\oplus b\)。所以这样是没问题的。

那么我们就得到了一个最短的线性基。

然后最好是再简化一下,遍历 \(i,j\),其中 \(i<j\),如果 \(p_j\)\(i\) 这一位也有值的话,那就异或一下。

如此操作之后所有基上的位都没有相同的位,而且它是最短的,长度不会超过 \(log\)。所以这样就可以了。

得到标准线性基之后,可以干如下事情:

  1. 查询最大异或和。直接输出线性基的异或和。

  2. 查询最小异或和。直接输出最小的那个基。

  3. 查询一个数 \(x\) 是否能被其他数异或出来。二进制分解。

  4. 查询异或第 \(k\) 小。可以遍历这个基,然后二进制分解一下,即可。

posted @ 2026-08-21 16:38  GUO120822  阅读(2)  评论(0)    收藏  举报