1. 程式人生 > 實用技巧 >高斯-約旦消元法

高斯-約旦消元法

一般的高斯消元需要回代,所以就顯得比較贅餘,一般選用高斯-約旦消元法

首先給定一個多元一次方程組

我們可以直接寫A出它的增廣矩陣直接求出他的解

同理對於方矩陣A

我們可以利用初等變化求出它的逆矩陣

證明如下:

對於矩陣(A,B)進行初等變化變為(E,P)易知p就是A的逆矩陣

關於高斯-約旦消元法就是利用此種方法求解

接下來進行初等變化

分為步

1.找出第I列的主元(元素值最大的那個)然後交換到第I行(已經交換到前面的就無需考慮)

2.求出對角線也就是第(i,i)個元素的逆元(由於需要mod,所以該逆元可以理解為他的倒數

3.直接更改當前行乘以逆元,你會發現第(i,i)個元素直接就是1

4.所以隨後只要減去1*該列除了主元以外其他元素的值,依次消元

如下圖所示1.

2.

3.

4.

程式碼如下

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
const int maxn=300;
const int mod=998244353;
ll a[maxn][maxn<<1];
ll quickpow(ll a,ll b,ll p)
{
    ll  ans=1;
    while (b)
    {
      if (b&1)///b為奇數
        ans=(ans*a)%p;
       a=(a*a)%p;///b為偶數
       b>>=1;
    }
    return ans;
}
for(re int i=1,t;i<=n;++i)
        {
          t=i;
          for(re int j=i+1;j<=n;++j)///找出每一列的最大主元
          {
            if(abs(a[j][i])>abs(a[t][i]))///找尋最大主元
            {
                t=j;
            }
          }
          if(i^t)///相當於i!=t,保證不在當前行
          {
            swap(a[i],a[t]);///交換行
          }
          ll w=quickpow(a[i][i],mod-2,mod);///直接求出對角元素值,方便消元

          for(re int j=1;j<=n;++j)
          {
            if(j!=i)///當前行直接乘以逆元即可,無需進行消元
            {
                ll tmp=a[j][i]*w%mod;///主元乘以逆元
                for(int k=i;k<=(n<<1);++k)
                {
                    a[j][k]=((a[j][k]-a[i][k]*tmp)%mod+mod)%mod;///該點元素直接減去i行元素乘以對稱點(i i)的逆元
                }

            }
          }
          for(re int j=1;j<=(n<<1);++j)a[i][j]=(w*a[i][j])%mod;///最後當前行直接乘以逆元保證主元為1,最後能得到單位矩陣
        }