行列式求值
给定一个行列式,求它的值,对任意模数取模。
分析
一个小技巧可以避免精度问题(或者说任意模数下逆元存在性问题),考虑使用类似求最大公约数地碾转相除法,在消除某行的主元时消到取余后的值,再交换两行重复上述步骤,直到消净(当然这种方法会牺牲对数级的复杂度)。
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=620;
int n,p,ans(1);
int a[N][N];
signed main(){cin>>n>>p;if(p==1) return puts("0"),0;for(int i=1;i<=n;++i)for(int j=1;j<=n;++j) cin>>a[i][j];assert(1);for(int i=1;i<=n;++i) if(!a[i][i]) return puts("0"),0;for(int i=1;i<=n;++i){for(int j=i;j<=n;++j){if(a[j][i]){for(int k=1;k<=n;++k) swap(a[j][k],a[i][k]);if(i^j) ans=ans*(p-1)%p;// 别忘了交换两行行列式的值取一次负break;}}for(int j=i+1;j<=n;++j){while(a[j][i]){if(a[i][i]>a[j][i]){for(int k=1;k<=n;++k) swap(a[j][k],a[i][k]);ans=ans*(p-1)%p;}int rate(a[j][i]/a[i][i]);for(int k=i;k<=n;++k){a[j][k]=(a[j][k]%p+p-rate%p*a[i][k]%p)%p;}}}}for(int i=1;i<=n;++i) ans=(ans+p)%p*a[i][i]%p;cout<<(ans+p)%p<<endl;
}