湘潭2017 ccpc中南地区邀请赛 Determinant 高斯约当求逆矩阵

链接  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),其中e(i=1,2,…,n) 为单位列向量;X为n个列向量构成的矩阵,即X=(x1,x2,…,xn),其中x(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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值