1. 程式人生 > >LUOGU P4783 【模板】矩陣求逆(高斯消元)

LUOGU P4783 【模板】矩陣求逆(高斯消元)

line org git == clu fas 解題思路 reg 操作

傳送門

解題思路

  用高斯消元對矩陣求逆,設\(A*B=C\)\(C\)為單位矩陣,則\(B\)\(A\)的逆矩陣。做法是把\(B\)先設成單位矩陣,然後對\(A\)做高斯消元的過程,對\(B\)進行同樣的操作,最後把\(A\)消成單位矩陣時,\(B\)就是其的逆矩陣。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

using namespace std;
const int N=405;
const int MOD=1e9+7;

inline int rd(){
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return f?x:-x;
}

int n,a[N][N],b[N][N];

inline int fast_pow(int x,int y){
    int ret=1;
    for(;y;y>>=1){
        if(y&1) ret=1ll*ret*x%MOD;
        x=1ll*x*x%MOD;
    }
    return ret;
}

bool gauss(){
    int tmp;
    for(int i=1;i<=n;++i){
        if(!a[i][i]){
            for(int j=i+1;j<=n;++j)
                if(a[j][i]) {
                    for(int k=1;k<=n;k++) swap(a[j][k],a[i][k]),swap(b[j][k],b[i][k]);
                    break;
                }
        }
        if(!a[i][i]) {puts("No Solution"); return 0;}
        tmp=fast_pow(a[i][i],MOD-2);
        for(int j=1;j<=n;++j)
            a[i][j]=1ll*a[i][j]*tmp%MOD,b[i][j]=1ll*b[i][j]*tmp%MOD;
        for(register int j=1;j<=n;++j)if(j!=i){
            tmp=a[j][i];
            for(register int k=1;k<=n;++k)
                a[j][k]=(a[j][k]-1ll*a[i][k]*tmp%MOD+MOD)%MOD,
                b[j][k]=(b[j][k]-1ll*b[i][k]*tmp%MOD+MOD)%MOD;
        }
    }
    return 1;
}

int main(){
    n=rd();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) a[i][j]=rd();
    for(int i=1;i<=n;i++) b[i][i]=1;
    if(gauss()){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)
                printf("%d ",b[i][j]);
            putchar('\n');      
        }   
    }
    return 0;
}

LUOGU P4783 【模板】矩陣求逆(高斯消元)