zoukankan      html  css  js  c++  java
  • [学习笔记]矩阵求逆

    以前只会高斯消元

    高斯消元可以O(n^4)解决

    但是可以做到O(n^3)

    考虑要求

    P*A=E

    E*A=A

    发现,高斯消元就是不断进行“交换两行,某一行乘上k,某一行乘上k加到另一行上去”

    这三种变换,都可以通过左乘一个唯一的矩阵等价得到!(而且手玩发现,如果开始另一个矩阵是单位矩阵,就是单位矩阵做同样的变化乘过去就是了)

    所以,开始让P=E

    然后A不断高斯消元向E靠拢,P同时做完全相同的操作

    最后A变成E,

    那么P乘A,就是E了。

    如果中途存在一个A[i][i]等于0,那么意味着无论如何不能削成单位矩阵。一定无解。(因为变换是可逆的,不可能一个A既能削成单位矩阵又不能)

    否则由于可以构造出P,一定有解。

    一种镜像映射的感觉

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=404;
    const int mod=1e9+7;
    int n;
    void _swap(int &x,int &y){
        x^=y^=x^=y;
    }
    struct tr{
        int a[N][N];
        int* operator [](int x){return a[x];}
        void swap(int x,int y){
            for(reg i=1;i<=n;++i) _swap(a[x][i],a[y][i]);
        }
        void mul(int x,int k){
            for(reg i=1;i<=n;++i) a[x][i]=(ll)a[x][i]*k%mod;
        }
        void mov(int x,int y,int k){//x+=y*k
            for(reg i=1;i<=n;++i) a[x][i]=((ll)a[x][i]+(ll)a[y][i]*k%mod)%mod;
        }
    }A,B;
    int qm(int x,int y){
        int ret=1;
        while(y){
            if(y&1) ret=(ll)ret*x%mod;x=(ll)x*x%mod;y>>=1; 
        }
        return ret;
    }
    int main(){
        rd(n);
        for(reg i=1;i<=n;++i){
            for(reg j=1;j<=n;++j){
                rd(A[i][j]);
            }
        }
        for(reg i=1;i<=n;++i) B[i][i]=1;
        bool fl=true;
        for(reg i=1;i<=n;++i){
            if(A[i][i]==0){
                for(reg j=i+1;j<=n;++j){
                    if(A[j][i]){
                        A.swap(i,j);B.swap(i,j);break;
                    }
                }
            }
            if(!A[i][i]) {
                fl=false;break;
            }
            B.mul(i,qm(A[i][i],mod-2));A.mul(i,qm(A[i][i],mod-2));
            for(reg j=i+1;j<=n;++j){
    //            if(A[j][i]){
                    B.mov(j,i,mod-A[j][i]);A.mov(j,i,mod-A[j][i]);
    //            }
            }
        }
    //    for(reg i=1;i<=n;++i){
    //        for(reg j=1;j<=n;++j){
    //            cout<<A[i][j]<<" ";
    //        }cout<<endl;
    //    }cout<<endl;
        if(!fl) puts("No Solution");
        else{
            for(reg i=n;i>=2;--i){
                for(reg j=i-1;j>=1;--j){
                    if(A[j][i]){
                        B.mov(j,i,mod-A[j][i]);A.mov(j,i,mod-A[j][i]);
                    }
                }
    //            for(reg k=1;k<=n;++k){
    //                for(reg j=1;j<=n;++j){
    //                    cout<<A[k][j]<<" ";
    //                }cout<<endl;
    //            }cout<<endl;
            }
            for(reg i=1;i<=n;++i){
                prt(B[i],1,n);
            }
        }
        
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/3/31 10:25:05
    */
    View Code
  • 相关阅读:
    7月自动化测试公开课通知
    招高级自动化测试工程师
    招聘软件开发工程师/开发实习生
    Selenium关键字驱动测试框架Demo(Java版)
    Eclipse+Selenium自动化测试脚本设计V1.0
    WebDriver基本API使用(基于Java)V1.0
    测试体系建设 免费咨询服务
    UFTQTP 12 新特性
    招聘自动化测试工程师
    AppScan学习笔记
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10630526.html
Copyright © 2011-2022 走看看