[總結] 行列式
概念類
數學家想找到一個由矩陣到數字的映射 \(f:M(R)->R\),於是有了行列式。
\(f\) 滿足以下條件:
- 行線性
- 行交錯性
- 規范性
稱這個函數值為行列式函數。
行線性
- 對矩陣一行乘上一個數 \(k\),函數值也乘上一個數 \(k\);
- 把矩陣第 \(i\) 行加到第 \(j\) 行 \((i\not=j)\) 上,函數值不變。
\[f\left( \begin{array}{cccc} a_1\\ a_2\times k\\ \cdots \\ a_n \end{array} \right ) = f\left( \begin{array}{cccc} a_1\\ a_2\\ \cdots \\ a_n \end{array} \right )\times k \]
\[f\left( \begin{array}{cccc} a_1\\ a_i\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) = f\left( \begin{array}{cccc} a_1\\ a_i+a_j\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) \]
行交錯性
如果一個矩陣有兩行相等,那么行列式函數值為 \(0\)。
\[f\left( \begin{array}{cccc} a_1\\ a_i\\ \cdots \\ a_i\\ \cdots \\ a_n \end{array} \right ) =0 \]
規范性
\[f(I_n)=1 \]
其中 \(I_n\) 表示 \(n\) 階單位方陣。
性質
- 矩陣轉置,行列式值不變。
- 矩陣行(列)交換,行列式值取反。
- 矩陣行(列)相加或相減,行列式值不變。
- 矩陣行(列)所有元素同時乘以數 \(k\),矩陣等比例變大。
考慮利用行線性的性質來證明第二條。
\[f\left( \begin{array}{cccc} a_1\\ a_i\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) = f\left( \begin{array}{cccc} a_1\\ a_i+a_j\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ), f\left( \begin{array}{cccc} a_1\\ a_j\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) =0 \]
可以得到:
\[f\left( \begin{array}{cccc} a_1\\ a_i\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) + f\left( \begin{array}{cccc} a_1\\ a_j\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) = f\left( \begin{array}{cccc} a_1\\ a_i+a_j\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) \]
也就是說:在這種情況下,兩個矩陣“相加”的行列式值可以拆分成兩個“子矩陣”行列式值的和。
所以:
\[f\left( \begin{array}{cccc} a_1\\ a_i\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) + f\left( \begin{array}{cccc} a_1\\ a_j\\ \cdots \\ a_i\\ \cdots \\ a_n \end{array} \right ) = f\left( \begin{array}{cccc} a_1\\ a_i+a_j\\ \cdots \\ a_i+a_j\\ \cdots \\ a_n \end{array} \right ) =0 \]
從而得到:
\[f\left( \begin{array}{cccc} a_1\\ a_i\\ \cdots \\ a_j\\ \cdots \\ a_n \end{array} \right ) =- f\left( \begin{array}{cccc} a_1\\ a_j\\ \cdots \\ a_i\\ \cdots \\ a_n \end{array} \right ) \]
行列式函數的性質
\[|\det(A)|=\sum\limits_{n階排列p}(-1)^{\tau(p)}\prod\limits_{i=1}^nA_{i,p_i} \]
證明的大體思路是把每一個向量 \(a_i\) 拆成線性組合的形式,把系數提出來,最后發現有貢獻的一定是排列,因為有重復行的矩陣函數值為 \(0\)。
這是行列式函數的核心所在,基本上所有的題都是根據這個公式表現出來的。
關鍵詞:逆序對,奇數比偶數多多少 \(\cdots\cdots\)
行列式的求解
利用通項公式來理解計算過程
核心是消成上三角矩陣,對角線乘積就是函數值。
這是因為削成上三角矩陣后行列式函數值不變,而且排列 \(p\) 的選取在有值的情況下唯一。
- 高斯消元法(非約旦)。
適用於整數有逆元或者小數的情況。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 600 + 10;
int n,P;
#define LL long long
#define read() read<int>()
LL a[maxn][maxn];
int main(){
n=read();P=read();
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=read<LL>();
LL ans=1;
for(int i=1;i<=n;i++){
if(!a[i][i]){
for(int j=i+1;j<=n;j++)if(a[j][i]){
swap(a[i],a[j]);ans=(P-ans);
break;
}
}
if(!a[i][i]){
ans=0;break;
}
ans=1LL*ans*a[i][i];
LL inv=power(a[i][i],P-2);
for(int j=i+1;j<=n;j++){
LL t=a[j][i]*inv%P;
for(int k=i;k<=n;k++)a[j][k]=(a[j][k]-t*a[i][k]%P+P)%P;
}
}
printf("%lld\n",ans);
return 0;
}
- 輾轉相除法。
注意,復雜度是 \(\text O(n^2(n+logn))\) 的。
適用於 \(P\) 非質數的情況。
行列式非零當且僅當矩陣的秩是 \(n\) ,也就是滿秩。
每次選取盡量小的數字作為輾轉相除時的 \(b\),常數小。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 600 + 10;
int n,P;
#define LL long long
#define read() read<int>()
LL G[maxn][maxn];
int main(){
n=read();P=read();
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=read<LL>();
LL ans=1;
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
while(G[j][i]){
LL t=G[i][i]/G[j][i];
for(int k=i;k<=n;k++)G[i][k]=(G[i][k]-t*G[j][k]%P+P)%P;
swap(G[i],G[j]);ans=(P-ans);
}
}
}
for(int i=1;i<=n;i++)ans=1LL*ans*G[i][i]%P;
printf("%lld\n",ans);
return 0;
}