矩阵求逆
矩阵求逆
如果矩阵 \(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;
}