线性代数

给数邱✌磕了/bx/bx/bx。

刚开学学的,期末的时候已经忘得差不多了。。。

主要还是记录一下线性代数在 OI 中的应用。

前置知识

矩阵,高斯消元。

行列式

定义

对于一个 \(n\times n\) 的矩阵 \(A\),其行列式记作 \(|A|\)\(\det(A)\),其值为:

\[|A|=\sum_p(-1)^{\tau(p)}\prod_{i=1}^{n}a_{i,p_i} \]

其中 \(p\) 为一个排列,\(\tau(p)\)\(p\) 的逆序对个数。

行列式的性质

  1. 交换矩阵的两行/两列,行列式取反

  2. 将行列式的一行/一列乘上一个数 \(k\),其行列式变为原来的 \(k\) 倍。

  3. \(A\) 中的某一行等于大小相同的矩阵 \(B,C\) 中的同一行的和,则有 \(\det(A)=\det(B)+\det(C)\)

  4. 将行列式的一行/一列的 \(k\) 倍加到另外一行/一列上,行列式的值不变。(与 3 同理)

  5. 若矩阵中有两行/两列程比例,则该矩阵行列式为 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. 交换两行。

根据行列式的性质 \((1)\),直接取反。

  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)\) 的。

口头描述不太清楚,具体可看代码。

code

特征多项式

定义

对于一个 \(n\) 阶方阵 \(A\),其特征多项式 \(f(x)\) 的定义为:

\[f(x)=|xI-A| \]

其中 \(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|\) 拆开,有递推式:

\[f_i(x)=(x-a_{i,i}) f_{i-1}(x)-\sum_{j=1}^{i-1}a_{i-j,i}(\prod_{k=i-j+1}^{i}a_{k,k-1})f_{i-j-1}(x) \]

这样我们就在 \(\operatorname{O}(n^3)\) 的时间内计算出了上海森堡矩阵的特征多项式。

接下来考虑如何将一个矩阵变为与其相似的上海森堡矩阵。

考虑高斯消元的过程,本质相当于将矩阵 \(A\) 变为了 \(PA\),那么我们要将其乘上 \(P^{-1}\)

高斯消元操作如下:

  1. 交换两行

  2. 将一行乘上常数 \(k\)

  3. 将一行加到另一行上。

感性理解一下会发现这三个操作想要附加到 \(P^{-1}\) 上只要对其对应的列也做一遍就可以了。

因此我们可以完成对矩阵求特征多项式了。时间复杂度 \(\operatorname{O}(n^3)\)

code

应用

题目描述:

给定 \(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=j\ 与\ i\neq j\ 的情况。 \]

  1. \(i=j\)

\[L_{i,i}=\sum_{k=1}^{n}M_{i,k}\times M^{T}_{k, i}=\sum_{k=1}^{n}M_{i,k}^2=deg\ i \]

  1. \(i\neq j\)

\[L_{i,j}=\sum_{k=1}^{n}M_{i,k}\times M^{T}_{k, j}=\sum_{k=1}^{n}M_{i,k}\times M_{j, k}=-cnt(i,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\),有:

\[|AB|=\sum_{S\subseteq\left\{1,2,\cdots,m\right\}\and|S|=n} |A[S]||B[S]| \]

证明不会。


现在可以开始考虑矩阵树定理了。注意到我们最终是需要在 \(m\) 条边中选择 \(n-1\) 条,所以丢掉一条边后信息不会丢失(丢掉第 \(i\) 行和第 \(i\) 列相当于计算以 \(i\) 为根的树的数量,因为是无向图所以直接可以钦定 \(1\) 为根)。

那么设 \(L'\) 表示将 \(L\) 的第一行和第一列删去后得到的矩阵,\(M'\) 同理,那么有:

\[|L'|=|M'M'^{T}| \]

用柯西-比内定理打开:

\[|L'|=\sum_{S\subseteq{1,2,\cdots,m}\and|S|=n-1}|M'[S]||M'^{T}[S]| \]

\[=\sum_{S\subseteq{1,2,\cdots,m}\and|S|=n-1}|M'[S]|^2 \]

只有 \(S\) 恰好为一个选边方案时才会产生贡献,因此 \(|L'|\) 就是树的数量。

例题

模板题

\(cnt(u,v)\) 设为 \((u,v)\) 的边权,\(deg\ u\) 设为所有 \(u\) 的出边的权值和,用矩阵树的结论即可。

[省选联考 2020 A 卷] 作业题

看到 \(\gcd\) 先直接莫反一下,之后就是求树的权值之和了。

注意到我们矩阵树定理的应用场景是求权值积之和,考虑进行转化。

对于这种和转化为乘积的问题可以考虑生成函数。设第 \(i\) 条边的权值是 \(e_i\),那么在矩阵树时将边权设为 \(1+e_ix\),那么边权和就是乘积的一次项系数。

直接做是 \(n^4\) 的,但注意到我们只需要一次项系数,那么每次卷积时对 \(x^2\) 取模就行了。时间复杂度 \(\operatorname{O}(n^3)\),封装一下多项式非常好写。

code

[ABC323G] Inversion of Tree

solution

posted @ 2025-07-09 16:35  caoshurui  阅读(52)  评论(2)    收藏  举报