矩陣求逆


矩陣求逆

如果矩陣 \(A\) 和矩陣 \(B\) 滿足 \(A\times B=E\) 則稱 \(B\)\(A\) 的逆矩陣。

如果有這樣的一個 \(B\) ,則稱 \(A\) 是非奇異的,否則稱其為奇異的。

並且,一個可逆矩陣的左逆矩陣等於右逆矩陣。證明:

\[AB=E,CA=E\Rightarrow CAB=B\Rightarrow C=B \]

\(det(A)\) 為矩陣 \(A\) 對應的行列式。\(det(AB)=det(A)det(B)\)

\[\exists X,AX=0\Rightarrow A奇異\\ det(A)\not=0\Leftrightarrow A 非奇異\\ (AB)^{-1}=B^{-1}A^{-1}\\ det(A^{-1})=det(A)^{-1} \]

1高斯約旦消元

不同點:高斯消元在每一次枚舉主元后,只會消下面的行,但該消元上面的行也消。

最終的矩陣為對角矩陣。

2矩陣初等變化

  • 用一個非零的數乘以某行。
  • 將某一行的 \(k\) 倍加到另一行。
  • 互換兩行。

單位陣 \(E\) 經過一次初等變換得到的矩陣成為初等矩陣。

一個矩陣乘上初等矩陣得到的結果等於對該矩陣進行一次初等變換。

對行進行變換相當於左乘,對列進行變換相當於右乘。

所以我們通過高斯消元把矩陣 \((A,E)\) 消成 \((E,B)\) 相當於我們對 \(A\) 左乘若干矩陣,對 \(E\) 左乘若干矩陣,不難發現 \(B\) 就是 \(A\) 的逆矩陣。

容易發現在矩陣乘法中,\(C\times (A,B)=(C\times A,C\times B)\)

於是我們可以用高斯消元來做。

代碼:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define int long long
#define ull unsigned long long
#define N 410
#define M number
using namespace std;

const int INF=0x3f3f3f3f;
const int mod=1e9+7;

template<typename T>  inline void read(T &x) {
	x=0; int f=1;
	char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	x*=f;
}

template<typename T>  inline void write(T x) {
	if(x < 0) x=-x,putchar('-');
	if(x > 9) write(x / 10);
	putchar(x%10+'0');
}

template<typename T>  inline void writeln(T x) {
	write(x);
	puts("");
}

int z[N][N*2],n,m;

inline int ksm(int a,int b){
    int res=1;
    while(b){
        if(b&1) (res*=a)%=mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

inline bool guass(){
	for(int a=1;a<=n;a++){
		for(int b=a;b<=n;b++)
			if(z[b][a]!=0){
				if(b==a) break;
				for(int c=1;c<=m;c++) swap(z[a][c],z[b][c]);
				break;
			}
		if(z[a][a]==0) return 0;
		int inv=ksm(z[a][a],mod-2);
		for(int b=1;b<=n;b++){
		    if(b==a) continue;
			int k=z[b][a]*inv%mod;
			for(int c=1;c<=m;c++){
			    z[b][c]-=z[a][c]*k;
			    z[b][c]=(z[b][c]%mod+mod)%mod;
            }
		}
		for(int c=1;c<=m;c++) z[a][c]=z[a][c]*inv%mod;
	}
	return 1;
}

signed main(){
    read(n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) read(z[i][j]);
        z[i][n+i]=1;
    }
    m=n*2;
    if(!guass()){
        printf("No Solution\n");
        return 0;
    }
    for(int i=1;i<=n;i++){
        for(int j=n+1;j<=m;j++){
            write(z[i][j]);putchar(' ');
        }
        puts("");
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM