【高斯消元】2021ICPC济南补题-J Determinant


题目链接

Description

Alice uses the excellent property of the matrix \(A^TA\) to find the determinant of the matrix \(A^TA\). Recall that the determinant of \(A\), denoted by \(det(A)\), satisfies \(det(A^TA)=det(A)^2\). Alice uses this property to find the absolute value \(∣det(A)∣\). But unfortunately, when \(∣det(A)≠0\), this method does not work out whether \(det(A)\) is positive or negative.

Now that you know the matrix \(A\) and the absolute value of \(det(A)\), determine whether it is positive or negative.

Input

An integer \(T (1≤T≤100)\) in the first line represents the number of test cases.

For each test case, the first line has an integer \(n (1≤n≤100)\), where the size of matrix \(A\) is \(n×n\).

The second line has a large number \(∣det(A)∣\). And it can be proved that \(∣det(A)∣\) has no more than \(10^4\) bits under the conditions in this problem.

The third to the \((n+2)\)-th lines, each with \(n\) numbers, describe this matrix. It is ensured that the absolute value of each number does not exceed \(10^9\).

Output

For each test case, output a single line with a character "+" or "-", indicating whether the determinant is positive or negative.

Sample Input

3
1
1
1
2
2
1 2
3 4
2
5
-1 2
3 -1

Sample Output

+
-
-

题意

\(T\)组数据,给定一个\(n*n\)的矩阵和它的行列式的绝对值,要求判断其行列式的值正负,数据范围 \(n (1≤n≤100)\) ,\(T (1≤T≤100)\)\(det(A)<=10^{10^4}\)

思路

(当时说巧不巧刚好没听那周的数论班讲的高斯消元,赛中有三道数学题要么知识点不会要么不会推理,属实是又痛苦又后悔,补题也痛苦死了...***,退钱)

首先,逐字符用模数处理\(det(A)\),变成一个小一点的可以比较的数,再计算行列式的值,对比一下是不是相等就知道是不是正数或者负数。

接着问题变成了怎么算行列式的值。又不能直接暴力解线性方程组。

这时候有一个很实用的数学方法,高斯消元,把矩阵消成一个阶梯的形状。

利用线性方程组实现过程:

一个\(n*m\)的矩阵,先找第一列是不是全为0,(如果是就跳过,跳到第二列)如果不是,找到第一个不为零的元素与第一行进行交换,(用线性代数里教的方法)用\(a_{11}\)把除其自身以外的该列所有元素消成0,其余同理,最终得到一个上三角行列式,从最后一行往上递推求解。

有一个很重要的点就是,必须取模,有些队伍带的板子没有取模的,据说这样也卡了一些人...
复杂度\(O(n^3)\)

代码

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define int long long
#define ull unsigned long long
#define PII pair<int,int>
#define endl '\n'
const int N = 100 + 10;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
typedef long long ll;
using namespace std;
int t, n;
int a[N][N];
string s;
int quickpow(int a, int b) {//快速幂
	int res = 1;
	while (b > 0) {
		if (b & 1) res = res * a % mod;
		b >>= 1;
		a = a * a % mod;
	}
	return res;
}
int getinv(int a) { return quickpow(a, mod - 2);}//费马小定理求逆元
int gauss(int n) {//高斯消元带模数
	int res = 1;
	for (int i = 1; i <= n; i++) {
		for (int j = i; j <= n; j++) {
			if (a[j][i]) {
				for (int k = i; k <= n; k++) {
					swap(a[i][k], a[j][k]);
				}
				if (i != j) {
					res = -res;
				}
				break;
			}
		}
		if (!a[i][i]) return 0;
		for (int j = i + 1, inv = getinv(a[i][i]); j <= n; j++) {
			int t = a[j][i] * inv % mod;
			for (int k = i; k <= n; k++) {
				a[j][k] = (a[j][k] - t * a[i][k] % mod + mod) % mod;
			}
		}
		res = (res * a[i][i] % mod + mod) % mod;
	}
	return res;
}
void init() {
	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= n; j++) {
			a[i][j] = 0;
		}
	}
	return;
}
void solve() {
	cin >> n;
	cin >> s;//由于题面说了det_a是一个不超过1e4长度的大数,数值肯定存不下,所以这里要先读入字符串再用模数处理一下
	init();//初始化
	int det_a = s[0] - '0';
	for (int i = 1; i <= s.length() - 1; i++) {
		det_a = ((det_a * 10) % mod + (s[i] - '0')) % mod;
	}//处理大数
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> a[i][j];
		}
	}//读入矩阵
	int sum = gauss(n);//高斯消元计算矩阵的值
	if (sum == det_a) cout << "+" << endl;//正数绝对值与自身相同,输出+
	else cout << "-" << endl;//负数绝对值与自身不同,输出-
	return;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	while (cin >> t) {
		while (t--) {
			solve();
		}
	}
	return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM