行列式

定义

对于一个大小为 \(n \times n\) 的矩阵 \(A\),定义 \(A\) 的行列式:

\[\begin{aligned} \det(A) &= { \begin{vmatrix} a_{1, 1} &a_{1, 2} &\cdots& a_{1, n} \\ a_{2, 1} &a_{2, 2} &\cdots& a_{2, n} \\ \vdots &\vdots &\ddots & \vdots \\ a_{n, 1} & a_{n, 2} &\cdots& a_{n, n} \end{vmatrix}} \\ &= \sum\limits_{p \in S_n} (-1)^{\pi(p)} \prod\limits_{i = 1}^n A_{i, p_i} \end{aligned} \]

其中 \(S_n\) 为全体长度为 \(n\) 的排列组成的集合,\(\pi(p)\) 为排列 \(p\) 的逆序对个数。

例如对于一个二阶矩阵 \(A = \begin{bmatrix} a & b \\ c & d \end{bmatrix}\)\(\det(A) = ad - bc\)

对于一个三阶矩阵 \(A = \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix}\)\(\det(A) = aei - afh - bdi + bfg + cdh - ceg\)(分别对应排列 \((1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)\))。

\[\begin{vmatrix} a_{1, 1} &a_{1, 2} &\cdots& a_{1, n} \\ a_{2, 1} &a_{2, 2} &\cdots& a_{2, n} \\ \vdots &\vdots &\ddots & \vdots \\ a_{n, 1} & a_{n, 2} &\cdots& a_{n, n} \end{vmatrix} \]

性质

  1. 矩阵行(列)所有元素同时乘以数 \(k\)\(A_i = kA_i\)),行列式 \(\times k\)\(A \rightarrow A', \det(A') = k\det(A)\)

  2. 交换两行或两列,行列式取相反数,\(A \rightarrow A', \det(A') = -\det(A)\)

  3. 如果将第 \(i\) 行的 \(k\) 倍加到第 \(j\) 列上(\(A_i = A_i + kA_j\)),行列式不变。对于列是同理的。

  4. 对于上三角矩阵,其行列式就是对角线上元素之积。\(\det(A) = \prod\limits_{i = 1}^n A_{i, i}\)(只有 \(p_i = i\) 时才有值)

求值

模板

使用高斯消元进行求解。

如果 \(A_{1, 1} = 0\),找到一个 \(A_{x, 1} \ne 0\),交换 \(A_1, A_x\)。如果这一列都是 \(0\),那么答案就为 \(0\)\(A_{i, i}\) 只能是 \(0\) 了)。记得交换要乘 \(-1\) 的系数。然后对把 \(A_{2, 1} \sim A_{n, 1}\) 都消成 \(0\) 即可。

对第 \(i = 2, 3, \dots n\) 做相同的事,只不过 \(x > i\) 而已。消成上三角矩阵即可快速求值。

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


这样做要求 \(p\) 为素数,因为要求逆元。(比如 \(p = 10, A_{i, i} = 4, A_{x, i} = 6\),需要进行 \(A_x = A_x - \frac{6}{4} A_i\) 的操作)

但是模板里 \(p\) 可以不是素数。解决方式是对两行进行辗转相除。还是上面那个例子,依次进行 \(A_{x} = A_x - A_i\)\(A_i = A_i - 2A_x\),再交换 \(A_i, A_x\),就能做到 \(A_i = 2, A_x = 0\) 了。

看上去时间复杂度是 \(O(n^3\log p)\)。但实际不是,因为每次都是 \(A_{i, i}\) 与其他数做辗转相除,实际上最多只会做 \(n + \log p\) 次。

所以总时间复杂度是 \(O(n^3 + n^2\log p)\)

for (int i = 1; i <= n; i++) {
  for (int x = i + 1; x <= n; x++) {
    while (a[x][i]) { // 将 a[x][i] 消成 0
      int k = a[i][i] / a[x][i];
      for (int y = 1; y <= n; y++) {
        a[i][y] -= 1ll * k * a[x][y] % Mod;
        if (a[i][y] < 0) a[i][y] += Mod;
      }
      ans = -ans, swap(a[i], a[x]); // 交换,记得要乘 -1!!
    }
  }
}
for (int i = 1; i <= n; i++) {
   ans = 1ll * ans * a[i][i] % Mod;
}

应用——矩阵树定理

模板

矩阵树定理对于无向图、有向图的情况都有,常见的是无向图,所以只讲无向图的情况。有向图见 oi-wiki(还要分内向树,外向树)。将 下文中矩阵 \(A\) 中的数值改改就行。

给定一张 \(n\) 个点的无向图 \(G\),求这张图的生成树个数。

我们构造一个 \(n \times n\) 的矩阵 \(A\)\(deg(u)\) 表示 \(u\) 的度数,那么:

\[A_{u, v} = \begin{cases} deg(u), u == v \\ -[(u, v) \in E], u \ne v\end{cases} \]

对于 \(A\),去掉任意一行一列,求行列式就是 \(G\) 的生成树个数。

变形

  1. 如果边带边权 \(w(u, v)\),定义生成树 \(T\) 地权值为 \(val(T) = \prod\limits_{(u, v) \in T} w(u, v)\),求 \(\sum val(T)\)

    只需要将 \(A_{u, u}\) 改为 \(u\) 连边的边权之和,\(A_{u, v}\) 改为 \(w(u, v)\) 即可。

  2. 如果继续改,\(val(T) = \sum\limits w(u, v)\),那么就是这道题:洛谷 P6624

  3. 一种特殊情况,对于一张完全图,有多少棵生成树?答案是 \(n^{n - 2}\),等价于求:

\[\begin{vmatrix} n - 1 & -1 &\dots & -1 \\ -1 & n - 1 &\dots & -1 \\ \vdots & \vdots & \ddots & \vdots \\ -1 & -1 &\dots & n -1 \\ \end{vmatrix}_{(n - 1) \times (n - 1)} \]

习题

洛谷 P4208

洛谷 P4336题解

洛谷 P5296题解

posted @ 2026-01-11 21:55  xiehanrui0817  阅读(6)  评论(0)    收藏  举报