高斯-约旦消元法
Posted qimang-311
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高斯-约旦消元法相关的知识,希望对你有一定的参考价值。
一般的高斯消元需要回代,所以就显得比较赘余,一般选用高斯-约旦消元法
首先给定一个多元一次方程组
我们可以直接写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,最后能得到单位矩阵
}
以上是关于高斯-约旦消元法的主要内容,如果未能解决你的问题,请参考以下文章