矩阵行列式

· · 个人记录

矩阵行列式是代表这个矩阵的一个值,最后的结果是一个数字,运算法则如下

首先最简单的是二维数组

jz[1][1] jz[1][2]

jz[2][1] jz[2][2]

其结果就是对角线相乘相减,即jz[1][1]jz[2][2]-jz[1][2]jz[2][1]

其余的高阶矩阵计算如下:

任一行(或一列)的值逐个乘上它的子矩阵的值并进行加减法

举个例子

因此以三阶矩阵(这次运用第一行)为例

a1 b1 c1
a2 b2 c2
a3 b3 c3
行列式值sum=a1*a1的子矩阵-a2*a2的子矩阵+a3*a3的子矩阵

先说明加减法的规则:

比如说a1是第一行第一列,那么就是(-1)^(1+1)=1,因此是加

a2是第二行第一列,那么就是(-1)^(2+1)=-1,因此是减

那么再来说明什么是子矩阵

子矩阵就是把去掉当前值所在的行和列剩余的矩阵

例如a1的子矩阵就是去掉第一行和第一列后剩余子矩阵的行列式的值

a2的子矩阵就是去掉第二行和第一列后剩余子矩阵的行列式的值

a2的子矩阵如下

a1 c1
a3 c3

那么知道了运算法则的时候,如何简便的运算呢

矩阵计算有以下性质:

1.交换任意两行(或两列)的值,矩阵行列式的值为原数的相反数。

2.任意一行(或一列)加上任意另外一行(或一列)的值乘k(k是任意值),矩阵行列式的值不变(以上面二维行列式举例子)

jz[1][1] jz[1][2]

jz[2][1] jz[2][2]

和

jz[1][1]+jz[2][1]*k jz[1][2]+jz[2][2]*k

jz[2][1]            jz[2][2]

算出来的矩阵行列式的值相同

因此以四阶矩阵(这次运用第一行)为例

a1 b1 c1 d1
a2 b2 c2 d2
a3 b3 c3 d3
a4 b4 c4 d4
行列式值sum=a1*a1的子矩阵-a2*a2的子矩阵+a3*a3的子矩阵-a4*a4的子矩阵

我们可以运用第二条将第2,3,4行加上一定倍数的第一行的话将a2,a3,a4的值变为0的话,那么sum=a1*a1的子矩阵

a1的子矩阵为

b2 c2 d2
b3 c3 d3
b4 c4 d4

同理,如果我们将b3,b4的值变为0的话,a1的子矩阵的值=b2*b2的子矩阵的值

。。。

所以只要将矩阵变为

x1 aa bb cc
 0 x2 dd ee
 0  0 x3 ff
 0  0  0 x4
矩阵行列式sum=x1*x2*x3*x4

特别的,如果对角线上的值为0的话,就在开头时将一行与这一行进行交换运用第一个运算规律,使得对角线上的值不为0再进行当前行刷0操作

所以矩阵用double定义,代码如下

#include<bits/stdc++.h>
using namespace std;
#define NU 205
typedef int rt;
inline rt read(){
    register char ch=getchar();register rt u=0,sign=1;
    while(!isdigit(ch)){if(ch=='-')sign=0;ch=getchar();}
    while(isdigit(ch)){u=(u*10)+(ch-48);ch=getchar();}
    return sign?u:-u;
} 
double sum;//结果 
int n;//行列数 
int num;//记录交换次数,最后转换正负 
double jz[NU][NU]; //double,后面有除法 
inline void init();
inline bool text();
inline void work();
inline void out();
void jzswap(int a,int b,int m)
{
    for(int i=1;i<=m;++i)
    swap(jz[a][i],jz[b][i]);
    return;
}
int main()
{
    init();
    work();
    out();
    return 0;
}
inline void init()
{
    n=read();
    for(int i=1;i<=n;++i)
    for(int j=1;j<=n;++j)
    jz[i][j]=read();
    return;
}
inline void work()
{
    sum=1.0;
    for(int i=1;i<=n;++i)
    {
        if(jz[i][i]==0)        //保证对角线的值不为0 
        for(int k=i+1;k<=n;++k)
        {
            if(jz[k][i]!=0)
            {
                jzswap(i,k,n);
                num++;
                break;
            }
        }
        for(int k=i+1;k<=n;++k)
        {
            if(jz[k][i]!=0)
            {
                double y=jz[k][i]/jz[i][i];  //计算出需要乘的系数值,运算法则2中k的值 
                for(int l=i;l<=n;++l)
                jz[k][l]-=jz[i][l]*y;        //将该列的对角线一下的值刷0,改行其余值跟着改变 
            }
        }
    }
    for(int i=1;i<=n;++i)
        sum*=jz[i][i];  //对角线相乘得到结果 
    if(num%2) sum=-sum; //运算法则1,交换次数为奇数则正负号变换 
    return;
}
inline void out()
{
    printf("%d\n",(int)sum); //记住转int
    return;
}