行列式基础:
约定:
- \(\tau(P)\) 表示排列 \(P\) 的逆序对数量
- \(det(A)=\sum\limits_{P}(-1)^{\tau(P)}\prod\limits_{i}^{n}A_{i,p_i}\)
引理:
引理1:对换(交换排列中任意两个元素)改变 \(\tau(P)\) 奇偶性:
考虑一次临项交换必定会使得逆序对数量 \(+-1\),一定会改变奇偶性。兑换 \((i,j),i<j\) 可以看成将 \(p_i\) 向右进行 \(i-j\) 次临项交换,将 \(a_j\) 向左进行 \(i-j-1\) 此临项交换。共进行了 \(2\times(i-j)-1\) 次,因此一定会改变排列逆序对数量的奇偶性。
引理2:行列交换,行列式值不变。
每一行只选一个,因此是对称的。
引理3:单位矩阵 \(I\) 的行列式的值为 \(1\)
除了对角线的排列,没得选。
类似的,上三角矩阵的行列式的值为 \(\prod\limits_{i=1}^{n}a_{i,i}\)。
引理3:交换两行,行列式变号。
只考虑这两行,相当于对每个排列在这两行做一次对换,奇偶性改变,因此行列式的值会变号。
引理4:给某一行 \(\times t\),行列式 \(\times t\)
这个是比较显然的,每一行只选一个,因此可以给他提出来这个 \(t\)。
引理5:行具有线性性
两个矩阵只有一行不一样,两个矩阵这一行对应相加之后的行列式的值=两个矩阵行列式的值相加。
还是每一行只选一个,因此对于某行中选了某个数的,给他展开之后就行了。
引理6:有两行一样的矩阵,行列式为 \(0\)
根据引理3,交换两行符号取反,但是矩阵没有边,相当于 \(det(A)=-det(A)\),即 \(det(A)=0\)。
引理7:用矩阵的一行加上另一行的倍数,行列式不变。
假设是第 \(i\) 行加到第 \(j\) 行,构造一个第 \(j\) 行和第 \(i\) 行都是原矩阵中第 \(i\) 行的矩阵。根据引理6,这个矩阵的行列式为 \(0\)。
给第 \(j\) 行 \(\times k\),根据引理4,矩阵的行列式仍为 \(0\)。
然后根据引理5,两个矩阵第 \(j\) 行对应相加之后的行列式等于之前两个行列式的值相加。
一个是零,一个是原矩阵,发现行列式的值就是原矩阵的。
高斯消元求行列式:
高斯消元其实只需要交换行,一行加上另一行的倍数,记录交换次数即可。
注意为了避免实数预算,使用辗转相减法做高斯消元,模板:
点击查看代码
int Gauss()
{int ans=1;for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){while(a[j][i]!=0){int d=a[i][i]/a[j][i];for(int k=i;k<=n && d;k++) a[i][k]=(a[i][k]-a[j][k]*d%mod+mod)%mod;swap(a[i],a[j]),ans=-ans;}}}for(int i=1;i<=n;i++) ans=ans*a[i][i]%mod;return (ans+mod)%mod;
}
注意:对于一些有规律的行列式,可以考虑展开后求递推式。
定义去掉某些行列的剩余部分行列式为余子式,然后代数余子式就是乘上 \((-1)^{sumrem_i+sumrem_j}=(-1)^{sumdel_i+sumdel_j}\)
设删掉 \(i,j\) 的余子式称为 \(M_{i,j}\);
那么就有 \(D=\sum\limits_{j=1}^{m}(-1)^{i+j}M_{i,j} \times a_{i,j}\)。
通过这个可以降阶。
更一般的表述是下面的定理:
拉普拉斯展开定理:在 \(n\) 阶行列式中,任意取定 \(k\) 行,由 \(k\) 行元素组成的所有 \(k\) 阶子式与代数余子式乘积之和等于行列式的值。
\(a_{i,j}\) 相当于为子式,\(M_{i,j} \times (-1)^{i+j}\) 相当于代数余子式。
[FJOI2007]轮状病毒 题解
矩阵树定理(Matrix-Tree Theorem)
矩阵树定理指出了一下事实:
定义 Kirchhoff 矩阵为:
\( K_{i,j}= \left\{ \begin{aligned} \sum\limits_{k!=i} w(i,k) & & i=j \\-w(i,j)& & i!=j \\ \end{aligned} \right. \)
其中 \(w(i,j)\) 表示边 \((i,j)\) 对 \(i\) 的影响(边的方向视情况而定)
记 \(M\) 为 \(K\) 删掉任意编号相同的行列后的矩阵 (\(n-1\) 阶子矩阵)
则 \(\sum\limits_{T}\prod\limits_{(u,v)\in T}w(u,v)=det(M)\)
其中删掉的行列是作为跟
应用
无向图生成树:
无论是求数量还是边权的乘积,都只用维护出 \(w\) 矩阵即可。
直接把无向边视为有向边,分别贡献 \(w()\) 即可。
有向图生成树
- 内向树:\(w(i,j)\) 表示边 \(i\rightarrow j\) 对 \(i\) 的贡献(出度)
- 外向树:\(w(i,j)\) 表示边 \(i \leftarrow j\) 对 \(i\) 的贡献(入度)
为啥是这样呢,考虑从删掉的一行一列考虑, 内向树跟没有出度,因此删掉他,统计他人的出度,外向树跟没有入度,统计他人入度。
例题与扩展:
-
[SHOI2016] 黑暗前的幻想乡
相当于统计每个恰好 \(0\) 人不参与的方案数,经典套路容斥,转化为钦定 \(i\) 人不参与,其余任意的方案数。
然后就是矩阵树定理模板了。
-
[SDOI2014] 重建
注意不选的边不选也是有概率的,不止和选了的边有关系。
考虑形式化列出要求的东西:
矩阵树定理能求的只能和选了的有关系,不选的部分我们用所有的除以选了的来处理(最关键点)
变成:
化简:
对于 \(0,1\) 用 \(eps\) 扰动一下即可。
-
[JSOI2010] 巨额奖金
最小生成树经典结论:
- 对于不同的最小生成树,边权相同的边总是数量相同的。
- 对于不同权值的边,互不影响,也就是加入每种权值得边贡献的连通性相同。
根据 Envy 的套路,想到了一个看起来很对的假做法:预处理出所有可能在最小生成树中边,然后直接跑矩阵树定理。
其实是错误的,因为这样对导致不同权值之间的边相互影响,使得某种边权的边贡献的连通性超过或不足自己本来应该贡献的。
hack数据:
点击查看代码
4
1 2 1
3 4 1
1 4 2
2 3 2
如果直接预处理,有可能连出两个 \(2\) 边权的生成树。
那怎么办呢:注意到每种边权的边贡献的连通性确定,也就是加入其他边权的任意树边后形成的连通块上,这种边权的边在做任意生成树,此时可以用矩阵树定理求出方案数。
由于不同权值的边互不影响,因此可以直接乘起来。
复杂度:设每种边权在 \(k\) 个联通块上做生成树,则总复杂度为 \(\sum\limits_{k} k^3 < n^3 (\sum\limits_{k} = n-1)\)
LGV 引理(LGV Lemma)
人话描述,证明省略。
定义与约定:
-
给定 \(n\) 个起点 \(\{a_i\}\) 和终点 \(\{b_i\}\),以及一张包含这些点的 DAG,保证起点无入度,终点无出度。
-
定义一条路径 \(P\) 的权值是经过所有边边权的乘积:\(W(P)=\prod\limits_{e \in P} w_e\)。
-
定义在排列上的路径 \(P_i\) 为 \(\{P_i: a_i \rightarrow b_{p_i},p \in S_n\}\),
其中 \(p\) 是这个路径组的排列,也就是起点对应的终点是谁。
-
定义一个路径组 \(P: \{P_i, p \in S_n\, i=\{1,2,3,…,n\}\}\)
如果这个路径组中不存在任何一个结点 \(u\),使得存在 \(i,j,i \not =j,u \in P_i,u \in P_j\),则称这个路径组为无交路径组,记为 \(P'\)。
路径组的权值为所有路径权值的乘积:\(W(P)=\prod\limits_{i=1}^{n}W(P_i)\)
-
构造矩阵 \(A \in \mathbb{Z}^{n \times n}\),其中 \(A_{i,j}=W(a_i,b_j)\),
其中 \(W(a_i,b_j)\) 就是从 \(a_i\) 到 \(b_j\) 的所有路径 \(P\) 的权值和:\(\sum W(P)\)。
LGV 引理的结论:
应用方法:
对于应用场景的要求:
-
必须在 DAG 上;
-
一般会要求所有路径无交。
对于最终结论的应用一般有两种:
-
直接和你说是逆序对数量偶减奇的方案数;
-
合法的不交路径唯一(没有逆序对),则此时路径的数量(权值)就是行列式的值。
对于细节分析和具体做法,确定 LGV 引理的三个要素:起点集合,终点集合,矩阵权值。
一般情况下要么在起点终点集合上做手脚,要么要求你快速算矩阵权值。
或者直接对着行列式的式子做排列的状压 Dp。
例题:
-
CF348D Turtles
需要你自己确定一下起点和终点 -
[NOI2021] 路径交点
需要思考正负号和逆序对的关系 -
[ABC216H] Random Robots
没有终点怎么办