线性代数
给数邱✌磕了/bx/bx/bx。
刚开学学的,期末的时候已经忘得差不多了。。。
主要还是记录一下线性代数在 OI 中的应用。
前置知识
矩阵,高斯消元。
行列式
定义
对于一个 \(n\times n\) 的矩阵 \(A\),其行列式记作 \(|A|\) 或 \(\det(A)\),其值为:
其中 \(p\) 为一个排列,\(\tau(p)\) 为 \(p\) 的逆序对个数。
行列式的性质
-
交换矩阵的两行/两列,行列式取反
-
将行列式的一行/一列乘上一个数 \(k\),其行列式变为原来的 \(k\) 倍。
-
若 \(A\) 中的某一行等于大小相同的矩阵 \(B,C\) 中的同一行的和,则有 \(\det(A)=\det(B)+\det(C)\)。
-
将行列式的一行/一列的 \(k\) 倍加到另外一行/一列上,行列式的值不变。(与
3同理) -
若矩阵中有两行/两列程比例,则该矩阵行列式为 0。
行列式求值
按照定义式计算行列式的复杂度是 \(\operatorname{O}(n!\times n)\) 的,无法接受,需要考虑优化。
不妨从一些特殊情况开始考虑,假设当前矩阵是一个上三角矩阵我们该怎么做(即对于矩阵 \(A\),\(\forall 1\le i<j\le n,a_{i,j}=0\))。
不难发现此时的行列式值就是 \(\prod_{i=1}^{n} a_{i,i}\),可以直接 \(\operatorname{O}(n)\) 计算。
既然如此,只要将一个矩阵变为上三角矩阵即可,所以可以考虑 高斯消元。
回顾高斯消元的第一步,我们就是将一个矩阵变为了上三角矩阵。考虑高斯消元中需要做的变换:
- 交换两行。
根据行列式的性质 \((1)\),直接取反。
- 将一行以 \(k\) 倍加到另一行上面去。
根据行列式的性质 \((4)\),行列式不变。
所以说只需要每次交换两行时记录取反次数,最终把对角线上的值乘起来即可。
于是我们做到了 \(\operatorname{O}(n^3)\) 计算行列式,瓶颈在于高斯消元。
例题
给定一个 \(n\) 阶行列式 \(A\),求 \(|A|\)。结果对 \(p\) 取模。
\(1\le n\le 600,\ 1\le a_{i,j}< 10^9+7,\ 1\le p\le 10^9+7\)
看到这题,我反手就是一个高斯消元上去。可他年轻人不讲武德,欺负我刚学线代的小同志,直接就是一个答案错误。
看到这道题,大部分人想法都是直接高斯消元,然后挂了。
注意数据范围不难发现,此题中的模数不是质数,不能直接高斯消元,考虑其他方法。
考虑类似辗转相除法进行消元。对于矩阵的两行的主元辗转相除,每次用对应的位置进行取模,直到一个的主元位置为 \(0\) 停止,根据辗转相除法的时间分析,总时间复杂度是 \(\operatorname{O}(n^3+n^2\log V)\) 的。
口头描述不太清楚,具体可看代码。
特征多项式
定义
对于一个 \(n\) 阶方阵 \(A\),其特征多项式 \(f(x)\) 的定义为:
其中 \(I\) 是一个 \(n\) 阶的单位矩阵,而 \(f(x)\) 是一个 \(n\) 次多项式。
根据此,定义满足 \(f(x)=0\) 的 \(x\) 为该矩阵的特征值。
矩阵相似
对于三个 \(n\times n\) 的矩阵 \(A,B,P\),若满足 \(A=PBP^{-1}\),则称 \(A\),\(B\) 为相似矩阵。
结论: 对于两个相似矩阵 \(A,B\),有 \(|xI-A|=|xI-B|\)。(即特征多项式相同)
证明:
\[|xI-B|=|xI-PAP^{-1}| \]\[=|xPIP^{-1}-PAP^{-1}| \]\[=|P(xI-A)P^{-1}| \]\[=|P|\times |P^{-1}| \times |xI-A| \]\[=|xI-A| \]
求解特征多项式
暴力
前面提到了 \(A\) 的特征多项式 \(f(x)\) 是一个 \(n\) 次多项式,所以可以直接将 \(x=0,1,2,\cdots\cdots,n\) 代入,然后用得到的值进行拉格朗日插值。
更快的方法
和求解行列式一样,我们不妨从一个比较简单的矩阵开始,这里引入一类比较特殊的矩阵,叫上海森堡矩阵。
上海森堡矩阵的特殊性在于任意的 \(i>j+1,a_{i,j}=0\),考虑这时怎么计算特征多项式。
记 \(A_i\) 表示保留 \(A\) 中 \((1,1)\) 到 \((i,i)\) 后的矩阵,\(f_i(x)\) 为其特征多项式,不难看出初值为 \(f_0(x)=1\)。
令 \(I_i\) 为大小为 \(n\) 的单位矩阵,根据定义 \(f_i(x)=|xI_i-A_i|\) 拆开,有递推式:
这样我们就在 \(\operatorname{O}(n^3)\) 的时间内计算出了上海森堡矩阵的特征多项式。
接下来考虑如何将一个矩阵变为与其相似的上海森堡矩阵。
考虑高斯消元的过程,本质相当于将矩阵 \(A\) 变为了 \(PA\),那么我们要将其乘上 \(P^{-1}\)。
高斯消元操作如下:
-
交换两行
-
将一行乘上常数 \(k\)
-
将一行加到另一行上。
感性理解一下会发现这三个操作想要附加到 \(P^{-1}\) 上只要对其对应的列也做一遍就可以了。
因此我们可以完成对矩阵求特征多项式了。时间复杂度 \(\operatorname{O}(n^3)\)。
应用
题目描述:
给定 \(n\times n\) 的矩阵 \(A\),\(B\),求 \(|A+xB|\)。
\(1\le n\le 300\)
看到这道题的第一反应是直接求行列式,但这样时间复杂度是 \(\operatorname{O}(n^5)\) 的,用 FFT 优化也只能优化到 \(\operatorname{O}(n^4\log n)\),无法通过。
设 \(I\) 为单位矩阵,先考虑一下两种特殊情况:
1. \(B=I\)
那么 \(|A+xB|=|A+xI|\),不难发现这个式子就是特征多项式(\(|xI-(-A)|\)),于是此时答案就是 \(-A\) 的特征多项式。
2. 存在 \(B'\) 满足 \(B'B=BB'=I\)(即 \(B\) 有逆元)
那么 \(|A+xB|=\frac{|AB'+xBB'|}{|B'|}=\frac{|xI-(-AB')|}{|B'|}\),直接矩阵求逆一下就行了。
通过前面两个例子的启发,我们可以发现只要把 \(B\) 转化为 \(I\) 那么就是好做的。但问题在于 \(B\) 不一定有逆元。
我们不妨回忆矩阵求逆的过程,之所以 \(B\) 没有逆元是因为某一行没有主元。而在这道题中,我们除了 \(B\) 外还有一个矩阵 \(A\),所以不妨通过 \(A\) 来让 \(B\) 拥有主元。
首先,在高斯消元时,如果 \(B\) 的第 \(i\) 行没有主元时可以直接把第 \(i\) 列 全部变成 \(0\)。不难发现,这时候我们将 \(A\) 的第 \(i\) 列乘上 \(x\) 就相当于交换 \(A\),\(B\) 的第 \(i\) 列,这样就可以让 \(B\) 的第 \(i\) 行存在主元了。
当然,可能会出现操作后 \(B\) 的第 \(i\) 行也没有主元的情况,考虑这时候的状况。这说明 \(A\),\(B\) 的第 \(i\) 列都为空,那么 \(|A+xB|\) 必然为 \(0\), 所以此时特征多项式就是 \(0\),可以特判掉。
通过这个操作,我们可以保证 \(B\) 能够变成 \(I\),那么套一个特征多项式板子就好了。
时间复杂度 \(\operatorname{O}(n^3)\)。
矩阵树定理
结论: 对于一个无向图 \(G\),设矩阵 \(D\) 满足 \(D_{i,i}\) 等于 \(i\) 的度数,\(A\) 为其邻接矩阵。将 \(A,D\) 中第一行和第一列删去得到 \(A',D'\),其生成树的数量为 \(|D'-A'|\)。
定义矩阵 \(L=D-A\)。
引理 1: 存在 \(n\times n\) 的矩阵 \(M\) 满足 \(M_{i,j}\) 表示将边随机定向后 \((i,j)\) 的个数减去 \((j,i)\) 的个数(不考虑重边,因此只会是 \(1\) 或 \(-1\)),使得 \(L=M\times M^{T}\)。
引理 1 证明:
- \(i=j\)
- \(i\neq j\)
其中 \(deg\ i\) 就是 \(i\) 的度数,\(cnt(i,j)\) 是 \(i\) 到 \(j\) 的边的数量。
引理 2(柯西-比内定理):'
对于集合 \(S\) 与矩阵 \(A\),定义 \(A[S]\) 表示保留所有 \(x\in S,y\in S\) 的 \(a_{x,y}\) 的矩阵(其它行/列全部删去)。
对于 \(n\times m\) 的矩阵 \(A\) 和 \(m\times n\) 的矩阵 \(B\),有:
证明不会。
现在可以开始考虑矩阵树定理了。注意到我们最终是需要在 \(m\) 条边中选择 \(n-1\) 条,所以丢掉一条边后信息不会丢失(丢掉第 \(i\) 行和第 \(i\) 列相当于计算以 \(i\) 为根的树的数量,因为是无向图所以直接可以钦定 \(1\) 为根)。
那么设 \(L'\) 表示将 \(L\) 的第一行和第一列删去后得到的矩阵,\(M'\) 同理,那么有:
用柯西-比内定理打开:
只有 \(S\) 恰好为一个选边方案时才会产生贡献,因此 \(|L'|\) 就是树的数量。
例题
将 \(cnt(u,v)\) 设为 \((u,v)\) 的边权,\(deg\ u\) 设为所有 \(u\) 的出边的权值和,用矩阵树的结论即可。
看到 \(\gcd\) 先直接莫反一下,之后就是求树的权值之和了。
注意到我们矩阵树定理的应用场景是求权值积之和,考虑进行转化。
对于这种和转化为乘积的问题可以考虑生成函数。设第 \(i\) 条边的权值是 \(e_i\),那么在矩阵树时将边权设为 \(1+e_ix\),那么边权和就是乘积的一次项系数。
直接做是 \(n^4\) 的,但注意到我们只需要一次项系数,那么每次卷积时对 \(x^2\) 取模就行了。时间复杂度 \(\operatorname{O}(n^3)\),封装一下多项式非常好写。

浙公网安备 33010602011771号