矩阵快速幂、求逆矩阵封装模板

矩阵模板

重载输入流 输出流 + *

矩阵快速幂 求逆矩阵

逆矩阵求法往下滑…

struct matrix{
    vector<vector<ll>>a;
    int n,m;
    matrix(int n,int m){
        this->n=n,this->m=m;
        a=vector<vector<ll>>(n+1,vector<ll>(m+1,0));
    }  
    matrix(int n,int m,char x){
        //单位阵
        this->n=n,this->m=m;
        a=vector<vector<ll>>(n+1,vector<ll>(m+1,0));
        for(int i=1;i<=min(n,m);i++)a[i][i]=1;
    }
    friend istream &operator>>(istream &input,matrix &B){
        for(int i=1;i<=B.n;i++){
            for(int j=1;j<=B.m;j++){
                input>>(B.a[i][j]);
            }
        }
        return input;
    } 
    friend ostream &operator<<(ostream &output,const matrix &B){
        for(int i=1;i<=B.n;i++){
            for(int j=1;j<=B.m;j++){
                output<<B.a[i][j]<<' ';
            }
            output<<'\n';
        }
        return output;
    }
    matrix operator + (const matrix &B){
        matrix sum(n,m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                sum.a[i][j]=this->a[i][j]+B.a[i][j];
                sum.a[i][j]%=mod;
            }
        }
        return sum;
    }
    matrix operator * (const matrix& B){
        matrix mul(n,B.m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=B.m;j++){
                for(int k=1;k<=m;k++){
                    mul.a[i][j]+=this->a[i][k]*B.a[k][j];
                    mul.a[i][j]%=mod;
                }
            }
        }
        return mul;
    }
    matrix pow(int k){//矩阵快速幂
        matrix ans(n,m,'E'),base=*this;
        while(k){
            if(k&1)ans=ans*base;
            base=base*base;
            k>>=1;
        }
        return ans;
    }
    matrix inreverse(){//求逆矩阵
        matrix tmp=*this,ans(n,m,'E');
        for(int i=1;i<=n;i++){
            int maxn=i;
            for(int j=i+1;j<=n;j++){
                if(tmp.a[j][i]>tmp.a[maxn][i])maxn=j;
            }
            swap(tmp.a[i],tmp.a[maxn]);
            swap(ans.a[i],ans.a[maxn]);
            if(tmp.a[i][i]==0)return matrix(0,0);//不存在
            for(int j=1;j<=n;j++){
                if(j==i)continue;
                ll base=tmp.a[j][i]*ksm(tmp.a[i][i],mod-2)%mod;
                for(int k=n;k>=1;k--){
                    ans.a[j][k]-=ans.a[i][k]*base%mod;
                    ans.a[j][k]=(ans.a[j][k]%mod+mod)%mod;
                    tmp.a[j][k]-=tmp.a[i][k]*base%mod;
                    tmp.a[j][k]=(tmp.a[j][k]%mod+mod)%mod;
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                ans.a[i][j]*=ksm(tmp.a[i][i],mod-2);
                ans.a[i][j]%=mod;
            }
        }
        return ans;
    }
};

逆矩阵的求解

A = [ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯ a m n ] . A = \begin{bmatrix} a_{1 1} & a_{1 2} & \cdots & a_{1 n} \\ a_{2 1} & a_{2 2} & \cdots & a_{2 n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m 1} & a_{m 2} & \cdots & a_{m n} \end{bmatrix} \text{.} A= a11a21am1a12a22am2a1na2namn .

比如A这个矩阵

只需要往右边补一个单位阵

即为

T = [ a 11 a 12 ⋯ a 1 n 1 0 ⋯ 0 a 21 a 22 ⋯ a 2 n 0 1 ⋯ 0 ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯ a m n 0 0 ⋯ 1 ] . T = \begin{bmatrix} a_{1 1} & a_{1 2} & \cdots & a_{1 n} & 1 & 0 & \cdots & 0\\ a_{2 1} & a_{2 2} & \cdots & a_{2 n} & 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \ddots & \vdots \\ a_{m 1} & a_{m 2} & \cdots & a_{m n} & 0 & 0 & \cdots & 1 \end{bmatrix} \text{.} T= a11a21am1a12a22am2a1na2namn100010001 .

然后只需要对矩阵进行初等变换

使得拼接的前半部分变为单位阵 此时右半部分的矩阵即为 A − 1 A^{-1} A1

正确性证明:

设左半矩阵为 A A A,右半矩阵为单位阵 E E E

初等行变换 即为 P A = E PA=E PA=E

A − 1 = P A^{-1}=P A1=P

而右半矩阵经过同等的初等行变换后即变为 P E = P = A − 1 PE=P=A^{-1} PE=P=A1

得证

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值