洛谷4783 【模板】矩阵求逆
题目
这是一道矩阵求逆的模板题。
先了解一下什么叫矩阵求逆:
两个矩阵A,B,BA=I(I为单位矩阵)
其次我们要了解矩阵的三种初等变换:
1.交换某两行。
2.将某一行的所有元素乘上k(k≠0)。
3.将某一行的所有元素乘上k加到另一行去。
根据这三种初等变换便可以进行高斯消元。
现将矩阵消成上三角矩阵,再将上三角矩阵消成对角矩阵,最后消成单位矩阵。
在消的途中,对一个单位矩阵进行相同的操作,便能得到这个矩阵的逆矩阵。
原理:
矩阵的三种初等变换可以用矩阵乘以原矩阵来得到结果。
例如:1.交换两行。交换第一行和第二行,可以让原矩阵乘以一个
这种类似单位矩阵的形式。
因此可知矩阵的初等变换可以写成矩阵乘法的形式。
那么矩阵A,经高斯消元后变为单位矩阵则可以表示为:
P1P2P3P4…Pn*A=I;即P1P2P3P4…Pn为矩阵A的逆元。
又因为一个单位向量乘以一个矩阵结果仍为这个矩阵,
因此对单位矩阵进行相同的操作后所得结果即为A的逆元。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=410;
const ll p=1e9+7;
int n,m;
ll f[maxn][2*maxn];
ll r,ret;
ll kuaisumi(ll u,ll v)
{
ret=1;
while(v)
{
if(v%2) ret=ret*u%p;
u=u*u%p;
v/=2;
}
return ret;
}
int main()
{
scanf("%d",&n);m=n*2;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
scanf("%lld",&f[i][j]);
f[i][n+i]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(f[j][i])
{
for(int k=1;k<=m;k++)
swap(f[i][k],f[j][k]);
break;
}
}
if(!f[i][i])
{
printf("No Solution");return 0;
}
r=kuaisumi(f[i][i],p-2);
for(int j=i;j<=m;j++)
f[i][j]=f[i][j]*r%p;
for(int j=1;j<=n;j++)
if(j!=i)
{
r=f[j][i];
for(int k=i;k<=m;k++)
{
f[j][k]=(f[j][k]-r*f[i][k]%p+p)%p;
}
}
}
for(int i=1;i<=n;i++,puts(" "))
for(int j=n+1;j<=m;j++) printf("%lld ",f[i][j]);
return 0;
}