zoukankan      html  css  js  c++  java
  • 【模板】矩阵求逆

    [PA=E, PE=P ]

    按照定义,P 即为 A 的逆矩阵。矩阵乘法可以看作是对右边矩阵的一个线性变换,即:A 经过 P 的线性变换变成了 E,E 经过同样的线性变换变成了 P。因此,只需要在高斯消元 A 矩阵,将 A 变成单位矩阵的同时,维护一个单位矩阵,做与 A 完全相同的线性变换即可得到逆矩阵。

    代码如下

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int mod = 1e9 + 7;
    
    typedef long long LL;
    
    LL fpow(LL a, LL b) {
    	LL ret = 1 % mod;
    	for (; b; b >>= 1, a = a * a % mod) {
    		if (b & 1) {
    			ret = ret * a % mod;
    		}
    	}
    	return ret;
    }
    
    struct matrix {
    	vector<vector<LL>> mat;
    	int n;
    	matrix(int _n) {
    		n = _n;
    		mat.resize(n + 1, vector<LL>(n + 1, 0));
    	}
    	void identify() {
    		for (int i = 1; i <= n; i++) {
    			mat[i][i] = 1;
    		}
    	}
    	vector<LL>& operator[](int x) {
    		return mat[x];
    	}
    	void add(int i, int j, LL val) {
    		for (int k = 1; k <= n; k++) {
    			mat[i][k] = (mat[i][k] + mat[j][k] * val % mod + mod) % mod;
    		}
    	}
    	void multiply(int i, LL val) {
    		for (int j = 1; j <= n; j++) {
    			mat[i][j] = (mat[i][j] * val % mod + mod) % mod;
    		}
    	}
    	void print() {
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= n; j++) {
    				cout << mat[i][j] << " ";
    			}
    			cout << endl;
    		}
    	}
    };
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	int n;
    	cin >> n;
    	matrix a(n), b(n);
    	b.identify();
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= n; j++) {
    			cin >> a[i][j];
    		}
    	}
    	auto gauss = [&]() -> bool {
    		for (int i = 1; i <= n; i++) {
    			if (a[i][i] == 0) {
    				for (int j = i + 1; j <= n; j++) {
    					if (a[j][i] != 0) {
    						swap(a[i], a[j]);
    						swap(b[i], b[j]);
    						break;
    					}
    				}
    			}
    			if (a[i][i] == 0) {
    				return 0;
    			}
    			LL inv = fpow(a[i][i], mod - 2);
    			a.multiply(i, inv);
    			b.multiply(i, inv);
    			for (int j = i + 1; j <= n; j++) {
    				b.add(j, i, -a[j][i]);
    				a.add(j, i, -a[j][i]);
    			}
    		}
    		for (int i = n - 1; i >= 1; i--) {
    			for (int j = i + 1; j <= n; j++) {
    				b.add(i, j, -a[i][j]);
    				a.add(i, j, -a[i][j]);
    			}
    		}
    		return 1;
    	};
    	if (gauss() == 1) {
    		b.print();
    	} else {
    		cout << "No Solution" << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    设计模式第四篇-工厂模式
    设计模式第三篇-装饰者模式
    设计模式第二篇-观察者模式
    设计模式第一篇-策略模式
    一元多项式的加/减法运算
    圆桌问题
    求有序序列的交集(链表)
    悲剧文本
    求序列的交集(链表)
    集合的操作
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/11575395.html
Copyright © 2011-2022 走看看