行列式学习笔记

前置知识

部分内容摘自 OI-Wiki

排列

1,2,,n 组成的有序数组称为 1,2,,n 的排列。前 n 个正整数的不同排列有 n! 个。

如果排列的逆序对个数是奇数,那么这是一个奇排列;如果排列的逆序对个数是偶数,那么这是一个偶排列。

置换

一个有限集合 S 到自身的双射(即一一对应)称为 S 的一个置换。集合 S={a1,a2,,an} 上的置换可以表示为

f=(a1,a2,,anap1,ap2,,apn)

其中 p1,p2,,pn1,2,,n 的一个排列。

对换

1,2,,n 的排列中,任意两个不同数 ij 交换,得到一个新的排列,这叫做一个对换,用 (i,j) 表示。

性质

  • 一个排列一定能通过若干次对换转换成另一个排列。
  • 一次对换会改变排列的奇偶性。

矩阵行列式

定义

对于一个矩阵:A=[a1,1a1,nan,1an,n],定义它的行列式为:

det(A)=p1,2n(1)π(p)i=1nai,pi

其中,p 表示 1,2,,n 的一个排列,π(p) 表示排列的逆序对个数。

性质

部分内容摘自 数学(5)——线性代数:行列式 - 洛谷专栏 (luogu.com.cn)

转置矩阵行列式不变(1)

矩阵 A 的转置矩阵为 AT,其中 Ai,j=Aj,iT

原因是排列 p1,p2,,pn 的奇偶性和 p1,p2,,pn(满足 ppi=i 的排列) 的奇偶性相同。

交换矩阵的两行(列),行列式取反(2)

原因是对原先枚举的排列 p 进行一次对换,其奇偶性改变。

对于列的证明,因为转置矩阵行列式不变,所以证明了行的性质也就证明了列的性质。

矩阵一行(列)所有元素同乘一个数,行列式也乘以这个数(3)

表示为 det[a1,1a1,2a1,nkai,1kai,2kai,nan,1an,2an,n]=k×det[a1,1a1,2a1,nai,1ai,2ai,nan,1an,2an,n]

如果矩阵 A 中某一行是(列)矩阵 B 和矩阵 C 中对应行(列)的所有元素之和,那么 det(A)=det(B)+det(C)(4)

表示为 det[a1,1a1,2a1,nbi,1+ci,1bi,2+ci,2bi,n+ci,nan,1an,2an,n]=det[a1,1a1,2a1,nbi,1bi,2bi,nan,1an,2an,n]+det[a1,1a1,2a1,nci,1ci,2ci,nan,1an,2an,n]

如果矩阵中某两行(列)成比例,那么其行列式为 0(5)

表示为 det[a1,1a1,2a1,nai,1ai,2ai,nkai,1kai,2kai,nan,1an,2an,n]=0

可以这样理解:把上面的第 i 行所有元素乘 k,于是得到相同的两行,交换这两行,矩阵不变,行列式不变;但因为交换了两行,所以啊行列式取反,因此行列式为 0

矩阵中一行(列)每个元素减去另一行(列)对应元素的若干倍,行列式不变(6)

表示为 det[a1,1a1,2a1,nai,1ai,2ai,naj,1aj,2aj,nan,1an,2an,n]=det[a1,1a1,2a1,nai,1ai,2ai,naj,1+kai,1aj,2+kai,2aj,n+kai,nan,1an,2an,n]

利用性质(4):det[a1,1a1,2a1,nai,1ai,2ai,naj,1aj,2aj,nan,1an,2an,n]=det[a1,1a1,2a1,nai,1ai,2ai,naj,1aj,2aj,nan,1an,2an,n]+det[a1,1a1,2a1,nai,1ai,2ai,nkai,1kai,2kai,nan,1an,2an,n]

最右边的矩阵第 i 行和第 j 行成比例,因此行列式为 0,由此得证。

上三角矩阵行列式为对角线的乘积(7)

其中上三角矩阵中指的是,只有在 ij 的时候第 i 行第 j 列才有值,反之值为 0

可以根据行列式的定义理解,只有当所有 pi=i 的时候后面的连乘才不是 0

同样,对于只有在 ij 的时候第 i 行第 j 列有值的下三角矩阵来说,其行列式也为对角线的乘积。

计算

利用性质(6),可以把矩阵像高斯消元一样转换成上三角矩阵,然后根据性质(7)求值。

当模数为质数的时候可以直接高斯消元:

点击开 D
for(i=1;i<=n;++i) {
    if(!a[i][i]) {
        for(j=i+1;j<=n;++j) if(a[j][i]) { k=i; break; }
        flag^=1,swap(a[i],a[k]);
    }
    Mul(ans,a[i][i]);
    inver=inv(a[i][i]);
    for(j=i+1;j<=n;++j) {
        muler=mul(inver,a[j][i]);
        for(k=i;k<=n;++k)
            Sub(a[j][k],mul(a[i][k],muler));
    }
}
if(flag) Mul(ans,moder-1);

但是当模数不是质数的时候,可能会出现 ai,i 没有逆元的情况,这个时候就要用类似辗转相除法的方法来消元:

点击开 D
for(i=1;i<=n;++i) {
    if(!a[i][i]) {
        for(j=i+1;j<=n;++j) if(a[j][i]) { k=i; break; }
        flag^=1,swap(a[k],a[i]);
    }
    for(j=i+1;j<=n;++j) {
        if(a[i][i]>a[j][i])
            flag^=1,swap(a[j],a[i]);
        while(a[j][i]) {
            flag^=1,swap(a[j],a[i]);
            muler=moder-a[j][i]/a[i][i];
            for(k=i;k<=n;++k)
                a[j][k]=(a[j][k]+muler*a[i][k])%moder;
        }
    }
    ans=ans*a[i][i]%moder;
}
if(flag) ans=(moder-ans)%moder;

<\details>

时间复杂度 O(n3)

posted @   fydj  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示