2107: Spoj2832 Find The Determinant III
Time Limit: 1 Sec Memory Limit: 259 MB
Submit: 154 Solved: 46
[Submit][Status][Discuss]
Description
Problem code: DETER3
Given a NxN matrix A, find the Determinant of A % P.
给出一个尺寸为N×N的整数方阵A(N≤200),要求求出|A|%P的值(即A的行列式的值除以P的余数)。方阵中的数与P均为32位有符号类型可容纳的整数
Input
The first line of every test case contains two integers , representing N
(0 < N < 201) and P (0 < P < 1,000,000,001). The following N
lines each contain N integers, the j-th number in i-th line represents
A[i][j] (- 1,000,000,001 < A[i][j] < 1,000,000,001).
Output
For each test case, print a single line contains the answer.
Sample Input
3 4
-840419217 -895520213 -303215897
537496093 181887787 -957451145
-305184545 584351123 -257712188
Sample Output
2
其实一说算法名称大概都会做了吧。高斯消元的除法本质上等效与辗转相处法,而辗转相处不存在精度误差。我们为了把两行之一消掉,通过辗转相除大行减小行变成类似子问题。
最开始尝试用java的BigDecimal,结果发现精度和时间是不可同时满足的。
矩阵行列式求法可几何理解,向量(基底)可以互相加减,而不影响体积,然而基底互换,有向体积取反。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MAXN 210 typedef long long qword; qword mat[MAXN][MAXN]; int main() { //freopen("input.txt","r",stdin); int n,m,x,y,z; int mod; while (~scanf("%d%d",&n,&mod)) { for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) { scanf("%lld",&mat[i][j]); mat[i][j]%=mod; } } int rev=1; for (int i=1;i<=n;i++) { x=-1; for (int j=i;j<=n;j++) { if (mat[j][i]) { x=j; break; } } if (x==-1)break; if (x!=i) { for (int j=1;j<=n;j++) swap(mat[x][j],mat[i][j]); rev=-rev; } if (!mat[i][i])break; for (int j=i+1;j<=n;j++) { while (mat[i][i]) { qword t=mat[j][i]/mat[i][i]; for (int k=1;k<=n;k++) mat[j][k]=(mat[j][k]-mat[i][k]*t)%mod; for (int k=1;k<=n;k++) swap(mat[j][k],mat[i][k]); rev=-rev; } for (int k=1;k<=n;k++) swap(mat[j][k],mat[i][k]); rev=-rev; } } qword ans=1; for (int i=1;i<=n;i++) ans=ans*mat[i][i]%mod; ans=(ans*rev+mod)%mod; printf("%lld\n",ans); } }