1. 程式人生 > 其它 >2021 ICPC濟南 J Determinant

2021 ICPC濟南 J Determinant

題意就是給定一個矩陣,然後給出他的行列式的絕對值,這個值是精確的,然後讓我們判斷行列式的正負。

思路來源:一個Acmer

首先做這個題要明白一個性質才可以做,一個數和它的相反數對一個奇數的取模一定不同,因此對於這個題而言,我們只需要選一個模數然後求行列式的值然後與給定的精確值取模後的結果相比較即可,也就是說如果我們算出來的值與給定值相同,那麼說明他倆同號,否則說明異號,然後來證明這個性質:

任意一對非\(0\)的相反數,有\(x_1 \not\equiv x_2 (\mod p)\)\(p\)為奇數,且\(x_1 \mod p \neq 0\)\(x_2 \mod p \neq 0\)

\[\begin{aligned} &x_1 + x_2 = 0\\ =>&(x_1 + x_2) \mod p = 0\\ =>&(x_1 \mod p + x_2 \mod p) \mod p = 0 \,\,\,\,\, (1)\\ \end{aligned} \]

假設\(x_1 \equiv x_2 (\mod p)\)

,那麼令\(t_1 = x_1 \mod p\)\(t_2 = x_2 \mod p\),那麼則有\(t_1 = t_2\),並且\(t_1 < p\)\(t_2 < p\)
那麼得知:

  • \(t_1 + t_2\)為偶數
  • \(t_1 + t_2 < 2 \times p \,\,\,\,\, (2)\)
    而把\(t_i (i = 1, 2)\)代入上面式子\((1)\)\((t_1 + t_2) \mod p == 0\),那麼說明\((t_1 + t_2) = kp\),由\((2)\)得知\(0 < k < 2\),那麼\(k = 1\),即\((t_1 + t_2) = p\)
    ,又因為\(p\)是奇數,而\((t_1 + t_2)\)是偶數,所以矛盾。

規則

  • 矩陣轉置,行列式不變
  • 矩陣行(列)交換,行列式取反
  • 矩陣行(列)相加減,行列式不變
  • 矩陣行(列)所有元素同時乘以一個數,行列式等比例變大
// Problem: P7112 【模板】行列式求值
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7112
// Memory Limit: 64 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 110, Mod = 1e9 + 7;
int a[N][N];
int n;

LL qmi(LL a, LL b, LL Mod) {
	LL res = 1;
	while (b) {
		if (b & 1) res = res * a % Mod;
		b >>= 1;
		a = a * a % Mod;
	}
	return res % Mod;
}

LL Guass() {
	LL det = 1;
	for (int i = 1; i <= n; i++) { //列舉列
		int k = i;
		for (int j = i + 1; j <= n; j++) //把最大的一行放到最上邊
			if (abs(a[j][i]) > abs(a[k][i])) k = j;
		if (abs(a[k][i]) == 0) { //如果斜線有0,結果就是0
			det = 0;
			break;
		}
		swap(a[i], a[k]); //把最大的一行放到最上邊
		if (i != k) det = -det; //如果有行交換,行列式取反
		det = (1ll * det * a[i][i] % Mod + Mod) % Mod; //結果貢獻
		for (int j = i + 1; j <= n; j++) {
			a[i][j]	= 1ll * a[i][j]	* qmi(a[i][i], Mod - 2, Mod) % Mod; //將每行的首位數變為1,這裡就是取模
		}
		for (int j = 1; j <= n; j++) {
			if (j != i && a[j][i]) {
				for (int l = i + 1; l <= n; l++) {
					a[j][l] = (a[j][l] - 1ll * a[i][l] * a[j][i] % Mod + Mod) % Mod; 
				}
			}
		}
	}
	
	return det;
}

int main() {
	int t;
	cin >> t;
	while (t--) {
		cin >> n;
		string s;
		cin >> s;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				cin >> a[i][j];
			}
		}	
		LL res = s[0] - '0';
		for (int i = 1; i < s.size(); i++) {
			res = (res * 10 % Mod + s[i] - '0') % Mod;
		}
		puts(res == Guass() ? "+" : "-");
	}

	return 0;
}