Luogu4783 【模板】矩阵求逆(高斯消元)

  对矩阵进行高斯消元直至消为单位矩阵,并在另一个单位矩阵上对其做同样的操作即可。

  模意义下的高斯消元可以直接计算系数来避免整行的辗转相除。

  还不知道有什么用。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define P 1000000007
#define N 410
int n,a[N][N],b[N][N];
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int ksm(int a,int k)
{
    if (k==0) return 1;
    int tmp=ksm(a,k>>1);
    if (k&1) return 1ll*tmp*tmp%P*a%P;
    else return 1ll*tmp*tmp%P;
}
int inv(int a){return ksm(a,P-2);}
void gauss()
{
    for (int i=1;i<n;i++)
    {
        if (!a[i][i])
        for (int j=i+1;j<=n;j++)
        if (a[j][i]) {swap(a[i],a[j]),swap(b[i],b[j]);break;}
        for (int j=i+1;j<=n;j++)
        if (a[j][i])
        {
            int x=a[j][i]/gcd(a[i][i],a[j][i]),y=a[i][i]/gcd(a[i][i],a[j][i]);
            for (int k=1;k<=n;k++)
            a[j][k]=(1ll*a[j][k]*y%P-1ll*a[i][k]*x%P+P)%P,
            b[j][k]=(1ll*b[j][k]*y%P-1ll*b[i][k]*x%P+P)%P;
        }
    }
    if (a[n][n])
    {
        for (int i=1;i<=n;i++)
        b[n][i]=1ll*b[n][i]*inv(a[n][n])%P;
        a[n][n]=1;
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    const char LL[]="%I64d
";
#else
    const char LL[]="%lld
";
#endif
    n=read();
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        a[i][j]=read(),b[i][j]=(i==j);
    gauss();
    for (int i=1;i<=n;i++) if (a[i][i]==0) {cout<<"No Solution";return 0;}
    for (int i=n;i>1;i--)
        for (int j=i-1;j>=1;j--)
        if (a[j][i])
        {
            int x=a[j][i]/gcd(a[i][i],a[j][i]),y=a[i][i]/gcd(a[i][i],a[j][i]);
            for (int k=1;k<=n;k++)
            a[j][k]=(1ll*a[j][k]*y%P-1ll*a[i][k]*x%P+P)%P,
            b[j][k]=(1ll*b[j][k]*y%P-1ll*b[i][k]*x%P+P)%P;
        }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        b[i][j]=1ll*b[i][j]*inv(a[i][i])%P;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        printf("%d ",b[i][j]);
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Gloid/p/9615445.html