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;
}