定義
對於一個 \(n\) 階方陣 \(A\),其行列式 \(|A|\)(也寫為 \(\det A\))定義為:
\[\sum_p(-1)^{\tau(p)}\prod_{i=1}^n a_{i,p_i} \]
其中 \(\sum_p\) 表示對 \(1,2,\cdots,n\) 的所有全排列 \(p\) 求和,\(\tau(p)\) 表示 \(p\) 的逆序對數。
形如:(未填的位置為 \(0\))
\[\left|\begin{matrix} a_{11} \\ a_{21} & a_{22}\\ \vdots & \vdots & \ddots\\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{matrix}\right|=\prod_{i=1}^na_{ii} \]
的行列式稱為下三角行列式,上三角行列式的定義同理。
性質
性質一 行列式與它的轉置行列式相等。
即:
\[\left|\begin{matrix} 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{matrix}\right| = \left|\begin{matrix} a_{11} & a_{21} & \cdots & a_{n1}\\ a_{12} & a_{22} & \cdots &a_{n2}\\ \vdots & \vdots & \ddots & \vdots\\ a_{1n} & a_{2n} & \cdots & a_{nn} \end{matrix}\right| \]
性質二 對換行列式的兩行或兩列,行列式變號。
性質三 行列式的某一行或某一列中所有的元素都乘以同一數 \(k\),等於用 \(k\) 乘以行列式。
即:
\[\left|\begin{matrix} a_{11} & a_{12} & \cdots & a_{1n}\\ \vdots & \vdots & & \vdots\\ ka_{r1} & ka_{r2} & \cdots & ka_{rn}\\ \vdots & \vdots & & \vdots\\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{matrix}\right|= k\left|\begin{matrix} a_{11} & a_{12} & \cdots & a_{1n}\\ \vdots & \vdots & & \vdots\\ a_{r1} & a_{r2} & \cdots & a_{rn}\\ \vdots & \vdots & & \vdots\\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{matrix}\right| \]
列同理。
性質四 行列式的某一行或某一列同乘以一個數然后加到另一行或另一列對應的元素上去,行列式不變。
即:
\[\left|\begin{matrix} a_{11} & a_{12} & \cdots & a_{1n}\\ \vdots & \vdots & & \vdots\\ a_{i1} & a_{i2} & \cdots & a_{in}\\ \vdots & \vdots & & \vdots\\ a_{j1} & a_{j2} & \cdots & a_{jn}\\ \vdots & \vdots & & \vdots\\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{matrix}\right| = \left|\begin{matrix} a_{11} & a_{12} & \cdots & a_{1n}\\ \vdots & \vdots & & \vdots\\ a_{i1} & a_{i2} & \cdots & a_{in}\\ \vdots & \vdots & & \vdots\\ a_{j1}+ka_{i1} & a_{j2}+ka_{i2} & \cdots & a_{jn}+ka_{in}\\ \vdots & \vdots & & \vdots\\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{matrix}\right| \]
列同理。
性質五 \(\det(AB)=\det A\det B\)
這個 NOI 好像還考了。
以上諸性質的證明留給讀者練習
行列式求值
根據性質二三四,可以使用高斯消元將一般行列式轉換為上三角或者下三角的形式,答案就是正對角線上所有數之積。
模板題:Luogu P7112
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=610;
int n,mod;
struct mat
{
int a[N][N];
mat(){memset(a,0,sizeof(a));}
mat operator *(const mat &x)const
{
mat ans;
for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
ans.a[i][j]+=1ll*a[i][k]*x.a[k][j]%mod,ans.a[i][j]%=mod;
return ans;
}
void init(){for(int i=1;i<=n;i++)a[i][i]=1;}
};
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
int det(mat x)
{
int ans=1;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
while(x.a[i][i])
{
int rate=x.a[j][i]/x.a[i][i];
for(int k=1;k<=n;k++)
x.a[j][k]=(x.a[j][k]-1ll*rate*x.a[i][k]%mod+mod)%mod;
for(int k=1;k<=n;k++)swap(x.a[i][k],x.a[j][k]);
ans*=-1;
}
ans*=-1;
for(int k=1;k<=n;k++)swap(x.a[i][k],x.a[j][k]);
}
}
for(int i=1;i<=n;i++)ans=1ll*ans*x.a[i][i]%mod;
return (ans+mod)%mod;
}
int main()
{
n=read(),mod=read();
mat x;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)x.a[i][j]=read();
printf("%d\n",det(x));
return 0;
}