链接 http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1260
要求逆矩阵还是第一次见到
题意 给定一个n-1*n的矩阵,要求依次求出删除第i列后的方阵的值
思路
先将n-1*n的矩阵化成n*n的方阵 值任意,那么它的逆矩阵的第一列去除原来的正负号,再乘上方阵的值(|A|)就是所要求的内容了
需要用高斯约当法先求出逆矩阵,假设AX=E,其中,A为n阶系数矩阵(与上面的解线性方程组对照);E为单位矩阵,即E=(e1,e2,…,en),其中ei (i=1,2,…,n) 为单位列向量;X为n个列向量构成的矩阵,即X=(x1,x2,…,xn),其中xi (i=1,2,…,n) 为列向量。于是,可以把等式AX=E看成是求解n个线性方程组Axi=ei (i=1,2,…,n),求出了所有的xi之后,也即得到了矩阵X。而由AX=E可知,矩阵X是A的逆矩阵,即X=A-1。这样,就求出了A的逆矩阵了。于是,求逆矩阵的过程被化成了解线性方程组的过程,因此我们可以用Gauss-Jordan消元法来求逆矩阵。
求解方法是把单位矩阵E附在A的右边,通过初等行变换将A化成单位矩阵,那么右边剩下的便是求出的逆矩阵了
代码就是模拟手算
对于此题,还没有结束,计算涉及除法,需要模1e9+7,求逆元,再将主对角线相乘得到方阵的值,注意,依据行列式的性质,行变换时,需乘-1,最后是还原逆矩阵的正负,因为逆矩阵是由伴随阵的代数余子式除|A|得到的,所以,i+j为奇数时,逆矩阵中的值是所要求的值的相反数,取反就可以了。
附上q巨的代码
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=205;
const int Mod=1000000007;
int a[MAXN][MAXN],b[MAXN][MAXN];
int fp(int a,int k)
{
int res=1;
while(k)
{
if(k&1)res=1LL*res*a%Mod;
a=1LL*a*a%Mod;
k>>=1;
}
return res;
}
void solve(int n)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
b[i][j]=(i==j);
int det=1;
for(int i=1;i<=n;i++)
{
int t=i;
for(int k=i;k<=n;k++)
if(a[k][i])t=k;
if(t!=i)det*=-1;
for(int j=1;j<=n;j++)
{
swap(a[i][j],a[t][j]);
swap(b[i][j],b[t][j]);
}
det=1LL*a[i][i]*det%Mod;
int inv=fp(a[i][i],Mod-2);
for(int j=1;j<=n;j++)
{
a[i][j]=1LL*inv*a[i][j]%Mod;
b[i][j]=1LL*inv*b[i][j]%Mod;
}
for(int k=1;k<=n;k++)
{
if(k==i)continue;
int tmp=a[k][i];
for(int j=1;j<=n;j++)
{
a[k][j]=(a[k][j]-1LL*a[i][j]*tmp%Mod+Mod)%Mod;
b[k][j]=(b[k][j]-1LL*b[i][j]*tmp%Mod+Mod)%Mod;
}
}
}
det=(det+Mod)%Mod;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
b[i][j]=1LL*det*b[i][j]%Mod;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int j=1;j<=n;j++)
a[1][j]=2;
for(int i=2;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
solve(n);
for(int i=1;i<=n;i++)
printf("%d%c",(i&1 ? b[i][1] : (Mod-b[i][1])%Mod)," \n"[i==n]);
}
return 0;
}