首页 > 其他分享 >高斯消元

高斯消元

时间:2022-10-25 16:14:43浏览次数:75  
标签:int 个数 元素 矩阵 一行 非零 高斯消

高斯消元是求解线性方程组的方法。对于一个 \(m\) 个等式 \(n\) 个未知数的方程组,我们可以将其写成 \(m \times (n + 1)\) 的增广矩阵的形式:
image

对于这个矩阵我们可以进行三种“初等行变换”操作:

  • 对一行内的所有元素乘以一个非零实数 \(k\)。(乘以 \(0\) 也成立,但是没有意义,算不出解)
  • 交换两行的元素。
  • 把其中一行的若干倍加到另一行上。

我们考虑通过将增广矩阵运用初等行变换操作的方式解出所有解。

具体步骤如下:

  • 遍历还没有处理的第 \(i\) 行。
    • 考虑目前需要消掉第 \(j\) 个元,也就是目标是让处理之后 \(i+1 \sim m\) 行里面第 \(j\) 个元的系数都是 \(0\)。
    • 先找到一个非零元素作为主元,将其所在的一行与第 \(i\) 行交换。如果有精度问题,那么当这个非零元素的绝对值为最大时,期望精度最好。利用 fabs(x) 函数计算浮点数 \(x\) 的绝对值。如果不存在非零元素,那么已经处理好第 \(j\) 个元,此时在不增加 \(i\) 的情况下处理第 \(j+1\) 个元。
    • 将第 \(i\) 行(也就是主元所在的一行)的第 \(j\) 个系数变为 \(1\),也就是整行除以这个系数。
    • 对于第 \(i+1 \sim m\) 行,每行减去该行内 \(j\) 的系数乘以第 \(i\) 行。
    • 如此,这些行都满足了要求。
  • 如此,矩阵变成了一个上三角矩阵。如下图所示。
    image
  • 现在要从底部一一代入已经求解好的值,从而把矩阵变成一个对角矩阵:
    image
  • 考虑解的个数。
    • 如果是上图的矩阵格式,那么有唯一解,也就是 \(x_1 = 1, x_2 = -2, x_3= 3\)。
    • 否则考虑零行。(也就是系数均为 \(0\) 的一行)。如果存在常数不为 \(0\) 的零行,那么无解。如果不是无解,那么自由元的个数就是总元的个数减去非零行的个数
      例如下图,当 \(x_1\) 确定为任何值的时候,都有一个 \(x_2\) 可以使得满足条件。也就是说存在一个自由元。(也就是一个非零行锁定一个元
      image
      image

代码实现:

其中 b[n][n + 1] 是增广矩阵,其中第 n+1 列是常数。
这里保证一定有唯一解。
(source:acwing 207)

void gauss() {
    //消成上三角矩阵
    f(i, 1, n) {
        //枚举把哪一列的元素求出,也就是哪一行换成上三角形式
        //找绝对值最大的元素作为非零元素(可以提升精度)
        int maxj = 0;
        f(j, i, n) if(fabs(b[j][i]) > fabs(b[maxj][i])) maxj = j;
        //交换
        f(j, i, n + 1) swap(b[i][j], b[maxj][j]);
        //归一,因为要用到最初的元素,所以倒着处理,下同
        for(int j = n + 1; j >= i; j--) b[i][j] /= b[i][i];
        //相减
        f(j, i + 1, n) for(int k = n + 1; k >= i; k--) b[j][k] -= b[i][k] * b[j][i]; 
    }
    //消成对角矩阵
    for(int i = n; i >= 1; i--) {
        f(j, 1, i - 1) {
            b[j][n + 1] -= b[j][i] * b[i][n + 1];
            b[j][i] = 0;
        }
    }
}

不保证唯一解。此时消去哪一行要和计算哪一个元的标号区分开。

(source:acwing 208)

void out() {
    //调试技巧,写成函数
    f(i, 1, n) f(j, 1, n + 1) cout << b[i][j] << " \n"[j == n + 1]; 
}
int gauss() {
    int h, l;
    for(h = 1, l = 1; l <= n; l++) {
        //h: 现在消哪一行。l: 现在消哪一个x。
        //异或,整数解,不关心精度问题
        //只需要找到第一个非零元素即可作为主元。
        int zy = 0;
        f(j, h, n) if(b[j][l]) {zy = j; break;}
        //没有非零元素就退出
        if(zy == 0) continue;
        
        //交换
        f(j, l, n + 1) swap(b[zy][j], b[h][j]); 
        //不用归一,因为一定是一
        //相减
        f(j, h + 1, n) for(int k = n + 1; k >= l; k--) {
            b[j][k] -= b[j][l] * b[h][k];
        } 
        h++;
    }
    //算答案,答案为 2 * 自由元个数,也就是 2 * 零行个数
    int ans = 1;
    if(h <= n) {
        f(i, h, n) {
            if(b[h][n + 1]) return -1;  //0 = !0, 无解
            else ans *= 2;  //多一个自由元
        } 
    }
    return ans;
}

标签:int,个数,元素,矩阵,一行,非零,高斯消
From: https://www.cnblogs.com/Zeardoe/p/16825196.html

相关文章

  • luogu P3232 [HNOI2013]游走 (期望, 高斯消元)
    https://www.luogu.com.cn/problem/P3232思路:算出每条边的期望访问次数,将期望访问次数多的赋予小的编号。一条边的期望访问次数=访问点u的期望/u的度+访问点v的期望......
  • CF963E Circles of Waiting(高斯消元,主元法)
    CF963ECirclesofWaiting平面直角坐标系上有一个点,开始在\((0,0)\),每秒钟这个点都会随机移动:如果它在\((x,y)\),下一秒它去\(4\)个方向的概率为\(p_0,p_1,p_2,......
  • 高斯消元
    盘活一下线性代数。我也不知道为什么看着格路计数然后看到LGV引理然后就来补线性代数了。高斯消元可以拿来干什么?解方程组。线性方程组。怎么解?我们现在有一个线性方程组......
  • Luogu P3389【模板】高斯消元法
    题意给定一个线性方程组,对其求解。$1\leqn\leq100,\left|a_i\right|\leq{10}^4,\left|b\right|\leq{10}^4$题解因为之前贺题解的时候没有理解高斯-约......
  • 异或方程组高斯消元模板
    inlinevoidsolve(intn){for(inti=1,top=1;i<=n;i++,top++){intcur=0;for(intj=top;j<=n;j++)if(m......
  • [补档]高斯消元做题记录/或曰 学习笔记
    早就退役啦!乍一看挺水的。P2455[SDOI2006]线性方程组板子题。codeP4035[JSOI2008]球形空间产生器给定一个\(n\)维的球体上\(n+1\)个点的坐标\(a_{i,j}\)。求......
  • 高斯消元详解
    高斯消元一,什么是高斯消元?用来解决需要解方程组的题目时所用的一种算法。适用于以下该种形式的式子:\[\begin{cases}a_1=k_{1,1}*x_{1,1}+k_{1,2}*x_{1,2}+\cdots+k_{1......
  • 实例92 高斯消去法
    #include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<math.h>intGS(int,double**,double*,double);double**TwoArrayAlloc(int,int);voidTwo......
  • 高斯消去
    importjava.util.Scanner;publicclassGaoSi{/***列主元高斯消去法*/staticdoubleA[][];staticdoubleb[];staticdoublex[];sta......
  • 高斯消去法(Gauss-Jordan方法)的Python实现
    高斯消去法的改进形式为Gauss-JordanEliminationMethod,要求每一行的主元素所在列元素全部消去为0,除了主元素本身。区别如下:代码实现如下:#-*-coding:utf-8-*-#@......