【luogu P4783】【模板】矩陣求逆(高斯消元)
阿新 • • 發佈:2022-03-23
【模板】矩陣求逆
題目連結:luogu P4783
題目大意
給你一個 n*n 的矩陣,要你求它的逆矩陣。
思路
也就是要找一個矩陣使得 \(AB=E\)(\(E\) 就是單位矩陣)。
然後你考慮弄三種矩陣的初等行變換。
交換兩行。
某一行乘上 \(k\)。
某一行加上某一行乘 \(k\)。
然後你考慮通過變換讓 \(A\) 變成 \(E\),然後這些操作就交給 \(B\),也就可以把一個 \(E\) 變成我們要的 \(B\) 了。
然後就用類似高斯消元,判無解的方法也跟高斯消元一樣。
然後搞就好啦。
程式碼
#include<cstdio> #include<algorithm> #define ll long long #define mo 1000000007 using namespace std; const int N = 400 + 1; int n; struct node { ll a[N][N]; void Swap(int x, int y) { for (int i = 1; i <= n; i++) swap(a[x][i], a[y][i]); } void Times(int x, ll k) { k = (k % mo + mo) % mo; for (int i = 1; i <= n; i++) a[x][i] = a[x][i] * k % mo; } void Mul(int x, int y, ll k) { k = (k % mo + mo) % mo; for (int i = 1; i <= n; i++) a[x][i] = (a[x][i] + a[y][i] * k % mo) % mo; } }A, B; ll ksm(ll x, ll y) { ll re = 1; while (y) { if (y & 1) re = re * x % mo; x = x * x % mo; y >>= 1; } return re; } ll inv(ll x) { return ksm(x, mo - 2); } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) scanf("%lld", &A.a[i][j]); for (int i = 1; i <= n; i++) B.a[i][i] = 1; for (int i = 1; i <= n; i++) { for (int j = i + 1; j <= n; j++) if (A.a[j][i]) { A.Swap(i, j); B.Swap(i, j); break; } if (!A.a[i][i]) { printf("No Solution"); return 0; } ll x = A.a[i][i]; x = inv(x); A.Times(i, x); B.Times(i, x); for (int j = i + 1; j <= n; j++) { x = -A.a[j][i]; A.Mul(j, i, x); B.Mul(j, i, x); } } for (int i = n; i >= 1; i--) for (int j = i + 1; j <= n; j++) { ll x = -A.a[i][j]; A.Mul(i, j, x); B.Mul(i, j, x); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) printf("%lld ", B.a[i][j]); puts(""); } return 0; }