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

题目链接

Description

Alice uses the excellent property of the matrix ATA to find the determinant of the matrix ATA. Recall that the determinant of A, denoted by det(A), satisfies det(ATA)=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(1T100) in the first line represents the number of test cases.

For each test case, the first line has an integer n(1n100), 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 104 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 109.

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组数据,给定一个nn的矩阵和它的行列式的绝对值,要求判断其行列式的值正负,数据范围 n(1n100) ,T(1T100)det(A)<=10104

思路

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

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

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

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

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

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

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

代码

#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;
}
posted @   TomiokapEace  阅读(365)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示