1. 程式人生 > 其它 >行列式&矩陣樹定理

行列式&矩陣樹定理

行列式:

參考

定義

對於一個\(n*n\)的矩陣A行列式取值(標量)
\(det(A)=|A|=\sum\limits_p(-1)^{\tau(p)}\prod\limits_{i=1}^na_{i,p_i}\)
\(\tau(p)\)即排列\(p\)的逆序對個數。

性質

證明後面再補

1.\(|A|=|A^T|\),即排列是按每行的排列得到的行列式等同於按每列的排列得到的行列式。
2.交換兩行(列),行列式取相反數
3.把一個矩陣的一行(列)的值全部乘一個常數加到另一行(列)上,行列式值不變。

求解

看看性質3,是不是很像高斯消元。
然後高斯校園後面得到的是一個倒三角矩陣。(除了這個斜下對角線排列,其它排列都含零)
畫畫圖可以發現,最後答案是\(\prod\limits_{i=1}^na_{i,i}\)

。中途注意維護一笑交換兩行帶來的正負的變化。
ps.下面這道題消元用的是輾轉相減(除),因為p不一定是質數,不一定能求逆元。
code【模板】行列式求值:

#include<bits/stdc++.h>
using namespace std;
const int N=605;
int n,p,a[N][N];
void Gauss() {
	int opt=1;
	for(int i=1;i<=n;i++) {
		for(int j=i+1;j<=n;j++) {
			while(a[i][i]) {
				int d=a[j][i]/a[i][i];
				for(int k=1;k<=n;k++) {a[j][k]-=1ll*a[i][k]*d%p;a[j][k]%=p;}
				opt=-opt;swap(a[i],a[j]);
			}
			opt=-opt;swap(a[i],a[j]);
		}
	}
	int ans=opt;
	for(int i=1;i<=n;i++)ans=1ll*ans*a[i][i]%p;
	printf("%d",(ans+p)%p);
}
int main() {
	scanf("%d%d",&n,&p);
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) {scanf("%d",&a[i][j]);}
	Gauss();
	return 0;
}