线性代数

给数邱✌磕了/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  阅读(105)  评论(2)    收藏  举报