定义
行列式是一个函数,定义域为任意方阵(行列数相等的矩阵),取值为一个标量。
可以如下表示方阵 \(A\) 的行列式:
\[\det(A)=\det(A_{ij})=|A|=\begin{vmatrix}
A_{11}&A_{12}&\cdots&A_{1n}\\
A_{21}&A_{22}&\cdots&A_{2n}\\
\vdots&\vdots&\ddots&\vdots\\
A_{n1}&A_{n2}&\cdots&A_{nn}
\end{vmatrix}
\]
定义 \(P_n\) 表示 \(1\) 到 \(n\) 的全排列集合,\(\tau(p)\) 表示排列 \(p\) 的逆序数,则:
\[\det(A)=\sum_{p\in P_n}(-1)^{\tau(p)}\prod_{i=1}^nA_{i,p_i}
\]
大致可以理解成相当于令 \(A_{i,j}\) 表示排列上第 \(i\) 位填 \(j\) 的价值,一个排列的价值为各位价值乘积,\(\det(A)\) 即为所有排列的价值乘上负一的其逆序数次方之和。
性质
为了方便,以下均以三阶方阵为例。
① 行列式 \(D\) 与其转置 \(D^T\) 等值。也就是说行和列等价。
\[\begin{vmatrix}
A_{11}&A_{12}&A_{13}\\
A_{21}&A_{22}&A_{23}\\
A_{31}&A_{32}&A_{33}\\
\end{vmatrix}
=
\begin{vmatrix}
A_{11}&A_{21}&A_{31}\\
A_{12}&A_{22}&A_{32}\\
A_{13}&A_{23}&A_{33}\\
\end{vmatrix}
\]
故而后文示例矩阵就只操作列了,行是一样的。
② 行列式的任一行或一列内所有元素同时乘 \(k\),等价于原行列式的值乘 \(k\)。即:
\[\begin{vmatrix}
A_{11}&kA_{12}&A_{13}\\
A_{21}&kA_{22}&A_{23}\\
A_{31}&kA_{32}&A_{33}\\
\end{vmatrix}
=
k\begin{vmatrix}
A_{11}&A_{12}&A_{13}\\
A_{21}&A_{22}&A_{23}\\
A_{31}&A_{32}&A_{33}\\
\end{vmatrix}
\]
这么想,排列上这一位不管选什么,价值均为原来 \(k\) 倍,故而总价值也是原来 \(k\) 倍。
③
\[\begin{vmatrix}
A_{11}&A_{12}+B_{12}&A_{13}\\
A_{21}&A_{22}+B_{22}&A_{23}\\
A_{31}&A_{32}+B_{32}&A_{33}\\
\end{vmatrix}
=
\begin{vmatrix}
A_{11}&A_{12}&A_{13}\\
A_{21}&A_{22}&A_{23}\\
A_{31}&A_{32}&A_{33}\\
\end{vmatrix}
+
\begin{vmatrix}
A_{11}&B_{12}&A_{13}\\
A_{21}&B_{22}&A_{23}\\
A_{31}&B_{32}&A_{33}\\
\end{vmatrix}
\]
同样按排列意义简单理解即可。
④ 交换行列式的两行或两列,值变为相反数。
\[\begin{vmatrix}
A_{13}&A_{12}&A_{11}\\
A_{23}&A_{22}&A_{21}\\
A_{33}&A_{32}&A_{31}\\
\end{vmatrix}
=
-\begin{vmatrix}
A_{11}&A_{12}&A_{13}\\
A_{21}&A_{22}&A_{23}\\
A_{31}&A_{32}&A_{33}\\
\end{vmatrix}
\]
首先临项交换是显然的,必然会使逆序数的奇偶性变化。
然后非临项交换可以等价为多次临项交换,并不难发现必然交换奇数次,得证。
⑤ 如果行列式中存在两行或两列完全相等,值为 \(0\)。
\[\begin{vmatrix}
A_{11}&A_{12}&A_{11}\\
A_{21}&A_{22}&A_{21}\\
A_{31}&A_{32}&A_{31}\\
\end{vmatrix}=0
\]
由上一个性质得到互换这两列互为相反数,但换完显然相等,故而为 \(0\)。
再结合 ② 于是也有:
\[\begin{vmatrix}
A_{11}&A_{12}&kA_{11}\\
A_{21}&A_{22}&kA_{21}\\
A_{31}&A_{32}&kA_{31}\\
\end{vmatrix}=0
\]
⑥ 给一列加上另一列的 \(k\) 倍,或者给一行加上另一行的 \(k\) 倍,值不变。
\[\begin{vmatrix}
A_{11}+kA_{13}&A_{12}&A_{13}\\
A_{21}+kA_{23}&A_{22}&A_{23}\\
A_{31}+kA_{33}&A_{32}&A_{33}\\
\end{vmatrix}
=
\begin{vmatrix}
A_{11}&A_{12}&A_{13}\\
A_{21}&A_{22}&A_{23}\\
A_{31}&A_{32}&A_{33}\\
\end{vmatrix}
\]
结合 ③⑤ 易证。
特殊行列式求值
首先是只有对角线上有值的行列式:
\[\begin{vmatrix}
A_{1}&0&\cdots&0\\
0&A_{2}&\cdots&0\\
\vdots&\vdots&\ddots&\vdots\\
0&0&\cdots&A_{n}
\end{vmatrix}=\prod_{i=1}^n A_{i}\\
\begin{vmatrix}
0&\cdots&0&A_{1}\\
0&\cdots&A_{2}&0\\
\vdots&\ddots&\vdots&\vdots\\
A_{n}&\cdots&0&0
\end{vmatrix}=(-1)^{\frac{n(n-1)}{2}}\prod_{i=1}^n A_{i}\\
\]
相当于只有一种排列有价值。同理,上三角和下三角也是差不多的,这里以下面两种为例:
\[\begin{vmatrix}
A_{11}&A_{12}&\cdots&A_{1n}\\
0&A_{22}&\cdots&A_{2n}\\
\vdots&\vdots&\ddots&\vdots\\
0&0&\cdots&A_{nn}
\end{vmatrix}
=
\begin{vmatrix}
A_{11}&0&\cdots&0\\
A_{21}&A_{22}&\cdots&0\\
\vdots&\vdots&\ddots&\vdots\\
A_{n1}&A_{n2}&\cdots&A_{nn}
\end{vmatrix}
=\prod_{i=1}^n A_{ii}\\
\]
行列式求值
因为性质 ⑥,我们可以考虑消元法将一般的行列式消成特殊行列式来求值。下面的两种方法均消成了上三角矩阵然后求值。
类高消法
考虑类似高斯消元那样,每次用 \(A_{i,i}\) 将第 \(i\) 列大于 \(i\) 的行上的值消成 \(0\) 即可。
特殊地,如果 \(A_{i,i}=0\),直接交换第 \(i\) 行和第 \(j\) 行即可,记得给答案乘上 \(-1\)。
inline flt det(vec<vec<flt>> v){
int n=v.size();flt res=1;
repl(i,0,n)repl(j,i+1,n){
if(fabs(v[i][i])<eps)swap(v[i],v[j]),res*=-1;
else{
flt d=v[j][i]/v[i][i];
repl(k,0,n)v[j][k]-=d*v[i][k];
}
}
repl(i,0,n)res*=v[i][i];
return res;
}
以及取模版本:
inline mint det(vec<vec<mint>> v){
int n=v.size();mint res=1;
repl(i,0,n)repl(j,i+1,n){
if(!v[i][i].x)swap(v[i],v[j]),res*=-1;
else{
mint d=v[j][i]/v[i][i];
repl(k,0,n)v[j][k]-=v[i][k]*d;
}
}
repl(i,0,n)res*=v[i][i];
return res;
}
辗转相减法
如果遇到精度问题或者没有逆元的情况,就无法使用类高消法了。但是由于我们可以自由交换两行,故而可以使用辗转相减法。
值得一提的是,经过势能分析,复杂度实际上是 \(O(n^3+n^2\log n)\) 的。
inline mint det(vec<vec<mint>> v){
int n=v.size();
mint res=1;
repl(i,0,n)repl(j,i+1,n){
while(v[i][i].x){
int d=v[j][i].x/v[i][i].x;
repl(k,0,n)v[j][k]-=v[i][k]*d;
swap(v[i],v[j]),res*=-1;
}swap(v[i],v[j]),res*=-1;
}
repl(i,0,n)res*=v[i][i];
return res;
}