前言
高斯大家应该都挺熟悉的吧,伟大的数学家,希望大家能够熟练掌握他的知识!!!
一、高斯消元的基本内容
高斯消元法(Gaussian Elimination)是一种重要的线性代数算法,用于求解线性方程组。具体来说,它是通过一系列初等变换(如行列互换、倍乘等),将原方程组转换为上三角系数矩阵的等价方程组,从而简化问题的形式,最终求出方程组的解。高斯消元法的关键在于如何构造上三角系数矩阵,这需要通过前向消去和反向替换两个步骤来实现。在前向消去过程中,通过初等变换将任意系数矩阵变换为一个具有上三角系数值的等价矩阵;而在反向替换阶段,则是从已经得到的等价方程组的解出发,逐步逆向回到原方程组以求得剩余的解。
高斯消元法的应用非常广泛,不仅限于线性方程组的求解,还包括矩阵的特征值计算、特征向量寻找等问题。此外,高斯消元法对于大规模方程组的处理也非常有效,因为它们能够减少方程的数量,使得计算机能够在有限时间内完成计算。然而,如果方程组非常大,可能需要采用更高级的方法,如迭代法和分块技巧,以加快运算速度。
总结一下,高斯消元法的主要特点和应用包括:
基本原理:通过初等变换将任意系数矩阵方程组转换为具有上三角系数矩阵的等价方程组。
核心步骤:分为前向消去和反向替换两个过程。
适用范围:广泛应用于线性方程组的求解、矩阵特征值计算等。
大规模方程组:在高斯消元法基础上可能还需要采用迭代法或其他技巧处理大型方程组。
二、例题:
1.高斯消元解线性方程组
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const double eps = 1e-6;
double a[N][N];
int n;
int gauss()
{
int r, c; // r表示当前所在的行数,c表示当前所指向的列数
for (r = 0, c = 0; c < n; c ++ ) {
// step1: 找到当前列下绝对值最大的行t
// 寻找绝对值最大的数是因为可以避免系数变得太大,精度较高.
int t = r;
for (int i = r; i < n; i ++ )
if (fabs(a[t][c]) < fabs(a[i][c]))
t = i;
// 如果当前这一列的最大数都是0,那么所有数都是0,那么就跳过该列,继续枚举下一列
if (fabs(a[t][c]) < eps) continue;
// 如果当前列下绝对值最大的数所在的行t和当前枚举的行r不同 那么执行step2
// step2: 让第t行与未固定的行(第r行)的第一行交换
if (t != r) {
for (int j = c; j <= n; j ++ )
swap(a[t][j], a[r][j]);
}
// step3: 将该行中的第一个非0的数化为1
// 这里必须从后往前做,假设我们从前往后做,那么就先把该行中的第一个非0的数a[r][c]化为1了,此时a[r][c]=1
// 但是它是一直循环的做,那么之后的数a[r][j]/=a[r][c]就等于a[r][j]/=1,也就等于a[r][j] 并没有改变
// 主要的原因就是你从前往后的话就先把a[r][c]变为1了 那么后面的数除以的就是被更新后的a[r][c] 而不是最初的a[r][c]
for (int j = n; j >= c; j -- )
a[r][j] /= a[r][c];
// step4: 将下面所有行的第c列变为0
for (int i = r + 1; i < n; i ++ ) {
// 只有当前行它的数不为0,才要进行削为0的操作
// 如果当前行它的数为零,说明不用进行削为零的操作
if (fabs(a[i][c]) > eps) {
// 这里也需要倒着做 原理同上
// 从后往前,当前i行的每个数字,都减去第i行的第c列a[i][c] * 第r行从第n列开始到第c列的每个数a[r][j]
for (int j = n; j >= c; j -- )
a[i][j] -= a[i][c] * a[r][j];
}
}
r ++ ; // 这一行的工作做完,换下一行
}
// 说明剩下方程的个数是小于n的,说明不是唯一解,判断是无解还是无穷多解
if (r < n) {
// 因为已经是阶梯型,所以r~n-1的值应该都为0
for (int i = r; i < n; i ++ )
if (fabs(a[i][n]) > eps) // 第i行的结果a[i][n]结果不是0 即出现了0 = 非0 所以无解
return 2;
return 1; // 否则,0=0,就是r~n-1的方程都是多余方程 所以有无穷多组解
}
// 说明有唯一解 自底向上回代结果
for (int i = n - 1; i >= 0; i -- )
for (int j = i + 1; j < n; j ++ )
a[i][n] -= a[i][j] * a[j][n];
return 0;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ )
for (int j = 0; j <= n; j ++ )
scanf("%lf", &a[i][j]);
int t = gauss();
if (!t) { // 有唯一解
for (int i = 0; i < n; i ++ ) {
// 可能会出现输出-0.00的情况 因此需要特判掉
if (fabs(a[i][n]) < eps) a[i][n] = 0;
printf("%.2lf\n", a[i][n]);
}
} else if (t == 1) { // 有无穷多组解
puts("Infinite group solutions");
} else puts("No solution"); // 无解
return 0;
}
2、高斯消元解异或线性方程组
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N][N], n;
int gauss() {
int r, c;
for (r = 0, c = 0; c < n; c ++ ) {
int t = r;
for (int i = r; i < n; i ++ ) {
if (a[i][c]) {
t = i;
break;
}
}
if (!a[t][c]) continue;
if (t != r) {
for (int j = c; j <= n; j ++ )
swap(a[t][j], a[r][j]);
}
for (int i = r + 1; i < n; i ++ ) {
if (a[i][c]) {
for (int j = n; j >= c; j -- )
a[i][j] ^= a[r][j]; // 也可以写成a[i][j] ^= a[i][c] & a[r][j]
}
}
r ++;
}
if (r < n) {
for (int i = r; i < n; i ++ )
if (a[i][n])
return 2;
return 1;
}
for (int i = n - 1; i >= 0; i -- )
for (int j = i + 1; j < n; j ++ )
a[i][n] ^= a[i][j] & a[j][n];
return 0;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n + 1; j++)
scanf("%d", &a[i][j]);
int t = gauss();
if (!t) {
for (int i = 0; i < n; i++)
printf("%d\n", a[i][n]);
}
else if (t == 1)
puts("Multiple sets of solutions");
else
puts("No solution");
return 0;
}