zoukankan      html  css  js  c++  java
  • 题解 P4783 【【模板】矩阵求逆】

    题目大意

    求一个N×N的矩阵的逆矩阵。答案对10^9+7取模。N<=400


    前置知识

    矩阵的初等变换

    矩阵的逆定义为 A*B=E(E为单位矩阵)此时B为A的逆 


    思路

    如果矩阵有逆

    那么这个矩阵经过一系列初等变化之后可以变为E

    设一系列初等变化分别为p1,p2,p3...px

    显然可得A*p1*p2*p3*...*px=E

    所以B=p1*p2*p3*...*px

    这样的话就很好做了

    我们利用高斯消元来让A逐渐变为单位矩阵

    设B初始为E

    B也跟着A同步变换

    那么到A变为单位矩阵时 B也就是p1*p2*p3*...*px的值了

    矩阵无逆的情况显然是高斯消元无法再消(a[1][i]-a[n][i]都为0时)特判输出就行哩


    代码

    #include<bits/stdc++.h> 
    using namespace std;
    #define ll long long
    #define C getchar()-48
    inline ll read()
    {
        ll s=0,r=1;
        char c=C;
        for(;c<0||c>9;c=C) if(c==-3) r=-1;
        for(;c>=0&&c<=9;c=C) s=(s<<3)+(s<<1)+c;
        return s*r;
    } 
    const ll N=410,p=1e9+7;
    ll n; 
    struct xin{
        ll a[N][N];
        //inline int* operator [](int x){return a[x];} //  b的话直接调用b[][] 
        inline void swap(int x,int y){for(int i=1;i<=n;i++) swap(a[x][i],a[y][i]);}
        inline void mul(int x,int k){for(int i=1;i<=n;i++) a[x][i]=(a[x][i]*k%p+p)%p;}//a[x]=k*a[y];
        inline void add(int x,int y,int k){for(int i=1;i<=n;i++) a[x][i]=((a[x][i]+a[y][i]*k)%p+p)%p;}// a[x]加k*a[y] 
        inline void prt()
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++) printf("%lld ",a[i][j]);
                printf("
    ");
            }
        }
    }a,b;
    inline ll ksm(ll a,ll b)
    {
        ll ans=1;
        while(b)
        {
            if(b&1) ans=(ans*a)%p;
            a=(a*a)%p;
            b>>=1;
        }
        return ans;
    }
    void gaosi()
    {
        for(int i=1;i<=n;i++)
        {
            if(!a.a[i][i]) for(int j=i+1;j<=n;j++) if(a.a[j][i])
            {
                a.swap(i,j);b.swap(i,j);
                break;
            }
            if(!a.a[i][i]){printf("No Solution
    ");exit(0);} 
            b.mul(i,ksm(a.a[i][i],p-2));a.mul(i,ksm(a.a[i][i],p-2));//把所有项除a[i][i] 变成a[i][i]变成1 
            for(int j=1;j<=n;j++)
            {
                if(i==j) continue; 
                b.add(j,i,-a.a[j][i]);a.add(j,i,-a.a[j][i]);//消去  b要放前面因为a放前面会被修改 
            }
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
          a.a[i][j]=read();
        for(int i=1;i<=n;i++) b.a[i][i]=1;
        gaosi();
        b.prt();
        return 0;
    }
  • 相关阅读:
    self 和 super 关键字
    NSString类
    函数和对象方法的区别
    求两个数是否互质及最大公约数
    TJU Problem 1644 Reverse Text
    TJU Problem 2520 Quicksum
    TJU Problem 2101 Bullseye
    TJU Problem 2548 Celebrity jeopardy
    poj 2586 Y2K Accounting Bug
    poj 2109 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/1436177712qqcom/p/10467470.html
Copyright © 2011-2022 走看看