核心是化为下三角型矩阵,然后对角线元素相乘,注意里面要使用辗转相除法,因为不保证 p 是一个质数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <bits/stdc++.h> #define MAXN 605 using namespace std; inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } int a[MAXN][MAXN]; int n,p; struct Matrix{ int n,m; int a[3][3]; void init(){ memset(a,0,sizeof(a)); for (int i=1;i<=n;++i) a[i][i]=1; } void reverse(){ a[1][1]=0,a[2][2]=0; a[1][2]=1,a[2][1]=1; } }; Matrix operator*(Matrix A,Matrix B){ Matrix C; C.n=A.n,C.m=B.m; for (int i=1;i<=C.n;++i){ for (int j=1;j<=C.m;++j){ C.a[i][j]=0; for (int k=1;k<=A.m;++k){ C.a[i][j]=(C.a[i][j]+1LL*A.a[i][k]*B.a[k][j]%p)%p; } } } return C; } namespace Gauss{ int Determinant(){ int sign=1; for (int i=1;i<=n;++i){ for (int j=i+1;j<=n;++j){ Matrix op; op.n=op.m=2; op.init(); while (a[i][i]){ int t=a[j][i]/a[i][i]; a[j][i]=(a[j][i]-1LL*a[i][i]*t%p+p)%p;
swap(a[i][i],a[j][i]);
Matrix s; s.n=s.m=2; s.a[1][1]=0,s.a[1][2]=1; s.a[2][1]=1,s.a[2][2]=-t;
op=op*s; sign=-sign; } swap(a[i][i],a[j][i]); sign=-sign; Matrix rev; rev.n=rev.m=2; rev.reverse(); op=op*rev; for (int k=i+1;k<=n;++k){ int aik=a[i][k],ajk=a[j][k]; a[j][k]=(1LL*op.a[1][1]*ajk%p+1LL*op.a[2][1]*aik%p)%p; a[i][k]=(1LL*op.a[1][2]*ajk%p+1LL*op.a[2][2]*aik%p)%p; } } } int ans=1; for (int i=1;i<=n;++i){ ans=ans*a[i][i]%p; } return ((ans*sign+p)%p+p)%p; } }; using namespace Gauss; int main(){ n=read(),p=read(); for (int i=1;i<=n;++i){ for (int j=1;j<=n;++j){ a[i][j]=read(); } } printf("%d",Determinant()); }
|
不知道为什么 T 了,不想卡常了。