求逆矩阵模板

高斯消元可以做到\(O(n^6)\)吧。

有一种很巧妙的做法:

我们知道:\(A*A^{-1}=E\),要求\(A^{-1}\)
设一个\(P=E\),那么一开始满足\(A*P=A\)

假设我们对右边的\(A\)做高斯消元,把它消成\(E\)
我们知道高斯消元每次的操作相当于右乘一个矩阵\(B\)
\((A*P)*B=A*B\)
\(A*(P*B)=A*B\)

也就是说,在右边的\(A\)进行消元时,对左边的\(P\)进行完全一样的操作。
那么最后就会得到\(A*P=E\)

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int mo = 1e9 + 7;

ll ksm(ll x, ll y) {
	ll s = 1;
	for(; y; y /= 2, x = x * x % mo)
		if(y & 1) s = s * x % mo;
	return s;
}

const int N = 105;

int n;
ll a[N][N], d[N][N], b[N][N], c[N][N];

int main() {
	n = 10;
	fo(i, 1, n)	fo(j, 1, n)
		a[i][j] = rand() % 10;
	fo(i, 1, n) fo(j, 1, n) d[i][j] = a[i][j];
	fo(i, 1, n) b[i][i] = 1;
	fo(i, 1, n) {
		int u = -1;
		fo(j, i, n) if(a[j][i]) {
			u = j; break;
		}
		if(u == -1) break;
		fo(j, 1, n) swap(a[i][j], a[u][j]), swap(b[i][j], b[u][j]);
		ll v = ksm(a[i][i], mo - 2);
		fo(j, 1, n) a[i][j] = a[i][j] * v % mo, b[i][j] = b[i][j] * v % mo;
		fo(j, 1, n) if(i != j && a[j][i]) {
			ll v = -a[j][i];
			fo(k, 1, n) a[j][k] = (a[i][k] * v + a[j][k]) % mo, b[j][k] = (b[i][k] * v + b[j][k]) % mo;
		}
	}
	fo(k, 1, n) fo(i, 1, n) fo(j, 1, n)
		c[i][j] = (c[i][j] + d[i][k] * b[k][j]) % mo;
	fo(i, 1, n) {
		fo(j, 1, n) pp("%lld ", c[i][j]);
		hh;
	}
}
posted @ 2020-03-31 17:54  Cold_Chair  阅读(232)  评论(0编辑  收藏  举报