[总结] 行列式
[总结] 行列式
概念类
数学家想找到一个由矩阵到数字的映射 \(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;
}