行列式
定义
对于一个大小为 \(n \times n\) 的矩阵 \(A\),定义 \(A\) 的行列式:
其中 \(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)\))。
性质
-
矩阵行(列)所有元素同时乘以数 \(k\)(\(A_i = kA_i\)),行列式 \(\times k\):\(A \rightarrow A', \det(A') = k\det(A)\)。
-
交换两行或两列,行列式取相反数,\(A \rightarrow A', \det(A') = -\det(A)\)
-
如果将第 \(i\) 行的 \(k\) 倍加到第 \(j\) 列上(\(A_i = A_i + kA_j\)),行列式不变。对于列是同理的。
-
对于上三角矩阵,其行列式就是对角线上元素之积。\(\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\),去掉任意一行一列,求行列式就是 \(G\) 的生成树个数。
变形
-
如果边带边权 \(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)\) 即可。
-
如果继续改,\(val(T) = \sum\limits w(u, v)\),那么就是这道题:洛谷 P6624
-
一种特殊情况,对于一张完全图,有多少棵生成树?答案是 \(n^{n - 2}\),等价于求:
浙公网安备 33010602011771号