欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[模板] 线性代数:矩阵/高斯消元/矩阵求逆/行列式

程序员文章站 2022-07-12 14:17:03
...

矩阵

struct tmat{
    int val[psz][psz];
    int* operator[](int p){return val[p];}
    int* operator[](int p)const{return val[p];}
    void cl(){memset(v,0,sizeof(v));}
}id{{{1,0},{0,1}}},zero{{{0,0},{0,0}}};
typedef const tmat& ctmat;

tmat operator+(ctmat a,ctmat b){
    tmat res=zero;
    rep(i,0,p-1){
        rep(j,0,p-1){
            res[i][j]=(a[i][j]+b[i][j])%nmod;
        }
    }
    return res;
}
tmat operator*(ctmat a,ctmat b){
    tmat res=zero;
    rep(i,0,p-1){
        rep(j,0,p-1){
                        if(a[i][j]==0)continue;
            rep(k,0,p-1){
                res[i][k]=(a[i][j]*b[j][k]+res[i][k])%nmod;
            }
        }
    }
    return res;
}

tmat qp(tmat a,int b){//a^b
    tmat res=id;
    while(b){
        if(b&1)res=res*a;
        a=a*a,b>>=1;
    }
    return res;
}

高斯消元

简介

求解n元一次方程组.

大概就是选 \(x_i\) 项系数最大的为主元, 然后用这个方程消去其他方程的 \(x_i\) 项的系数.

代码

// arr: n*(n+1) 矩阵
// ans: 答案
int gauss(db *ans){
    db tmp;
    rep(i,1,n){
        int p0=i;
        rep(j,i+1,n)if(fabs(a[p0][i])<fabs(a[j][i]))p0=j;
        if(fabs(a[p0][i])<eps)return 0;
        if(p0!=i)rep(j,1,n+1)swap(a[i][j],a[p0][j]);
        tmp=a[i][i];
        rep(j,i,n+1)a[i][j]/=tmp;
        rep(j,1,n){
            if(j==i)continue;
            tmp=a[j][i];
            rep(k,i,n+1)a[j][k]-=a[i][k]*tmp;
        }
    }
    rep(i,1,n)ans[i]=a[i][n+1];
    return 1;
}

行列式

行列式的性质

MIT—线性代数笔记18 行列式及其性质 - 知乎

行列式的显式公式

  1. (展开公式)

    \((i_1, i_2, \cdots, i_n)\)\((1, 2, \cdots, n)\) 的一个排列, 共 \(n!\) 个;
    \(\delta(S) = (-1)^s \in \{1, -1\}\), \(s\)\(S\) 的逆序对数目.
    \[ \left| A \right| = \sum_{(i_1, i_2, \cdots, i_n)}\delta(i_1, i_2, \cdots, i_n)a_{1,i_1}a_{2,i_2}...a_{n,i_n} \]

  2. (代数余子式)

    \(A_{i,j}\) 表示 \(A\) 的余子式, 即去掉 \(i\) 行和 \(i\) 列剩下方阵的行列式;
    \(a_{i,j}\) 表示 \(A\)\(i\)\(i\) 列的值.

    \[ \left| A \right| = \sum_{i=1}^n (-1)^{i+j} a_{i,j} A_{i,j} \quad (\forall j \in \{1, 2, \cdots, n\})\]

    \[ \left| A \right| = \sum_{j=1}^n (-1)^{i+j} a_{i,j} A_{i,j} \quad (\forall i \in \{1, 2, \cdots, n\})\]

    递归终点: \(M_1\)\(1\)\(1\) 列的矩阵,

    \[ \left| M_1 \right| = m_{1,1}\]

    即选中 \(A\) 的某一行/列, 对这一行/列的所有元素分别求余子式.

  3. (消元法)

    \(A\) 利用高斯消元将其变为上三角矩阵 \(A'\), 记 \(s\) 为高斯消元过程中进行行交换的次数, 那么
    \[ \left| A \right| = (-1)^s \cdot \prod_{i=1}^n A'_{i,i} \]

其中第3个方法相对易于实现, 比较常用.

代码

//利用消元法
//模意义下
//实数上类似
ll a[nsz][nsz];
ll det(int n){
    ll ans=1;
    ll v,tmp;
    rep(i,1,n){
        int p0=i;
        rep(j,i+1,n)if(abs(a[p0][i])<abs(a[j][i]))p0=j;
        if(a[p0][i]==0)return 0;
        if(p0!=i){ans=-ans;rep(j,1,n)swap(a[i][j],a[p0][j]);}
        v=inv(a[i][i]),ans=ans*a[i][i]%nmod;
        rep(j,1,n){
            if(j==i)continue;
            tmp=v*a[j][i]%nmod;
            rep(k,i,n)a[j][k]=(a[j][k]-tmp*a[i][k])%nmod;//possibly -
        }
    }
    return getv(ans%nmod);
}

矩阵求逆

简介

对于 \(n\) 阶方阵 \(A\), 求矩阵 \(A^{-1}\), 满足 \(A A^{-1} = ID\), 其中\(ID\)为单位矩阵.

令矩阵 \(S\) 为单位矩阵. 利用高斯消元将 \(A\) 变为单位矩阵的同时, 对 \(S\) 进行相同操作.

最后的 \(S = A^{-1}\).

代码

struct tmat{
    ll val[nsz][nsz];
    ll *operator[](int p){return val[p];}
    const ll *operator[](int p)const{return val[p];}
    void cl(){memset(val,0,sizeof(val));}
    void getid(){
        cl();
        rep(i,1,n)val[i][i]=1;
    }
    //elementary row operations
    void swap(int x,int y){rep(i,1,n)swap(val[x][i],val[y][i]);}
    void mul(int x,ll k){rep(i,1,n)val[x][i]=getv(val[x][i]*k%nmod);}
    void add(int x,ll k,int y){rep(i,1,n)val[x][i]=getv((val[x][i]+val[y][i]*k)%nmod);}//x+=k*y
    void pr(){
        rep(i,1,n){
            rep(j,1,n)cout<<val[i][j]<<' ';
            cout<<'\n';
        }
    }
}a,b;

bool invmat(tmat a,tmat &b){
    b.getid();
    rep(i,1,n){
        if(a[i][i]==0){
            rep(j,i+1,n){
                if(a[j][i]){
                    a.swap(i,j),b.swap(i,j);
                    break;
                }
            }
        }
        if(a[i][i]==0)return 0;
        b.mul(i,inv(a[i][i])),a.mul(i,inv(a[i][i]));
        rep(j,1,n){
            if(j==i)continue;
            b.add(j,-a[j][i],i),a.add(j,-a[j][i],i);
        }
    }
//  a.pr();
    return 1;
}

上一篇: Spring—AOP

下一篇: Spring AOP