数论--高斯消元法
高斯消元是一个常用的解n元一次方程组的方法。
1.处理数据:
我们设方程
那么对于
例如这样:
存储为矩阵:
2 4 10
-3 2 1
2.矩阵变换:
我们可以对于矩阵的某一部分作出一些变换使得在方程组本身没有本质变化的前提下可以求解。
变换1:交换两行。
变换2:给一行乘(除)一个数。
变换3:将某一行加(减)给另一行。
变换2+3:将某一行乘(除)一个数之后再加(减)给另一行。
以上的变换一定要好好理解。
3.矩阵求解:
首先,我们先来看看上面那个方程是怎么解的:
1
2
3
4
以上过程转换成矩阵就是:
1
2 4 10
-3 2 1
2
R1/2
1 2 5
-3 2 1
3
R2+R1*3
1 2 5
0 8 16
4
R2/8
1 2 5
0 1 2
5
R1-R2*2
1 0 1
0 1 2
6
此时的矩阵转换为方程就是:
化简后即为:
至此,解题完毕。
看了以上过程之后是不是有点儿明白了呢?
可以先看看代码,一边看,一边自己用代码来处理一下上面的题,有助于理解。
代码:洛谷 P3389 【模板】高斯消元法
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps=1e-8;
int n;
double a[101][102];
bool gauss(){
for(int i=1;i<=n;i++){//依次从x1到xn消去每一个未知数
int mx=i;//有一个优化我还没说,就是每次找绝对值最大的一行,可以减小精度误差
for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[mx][i]))mx=j;
if(fabs(a[mx][i])<eps)return 0;//几乎为零,这种情况下无解或有无穷多解
for(int j=i;j<=n+1;j++)swap(a[i][j],a[mx][j]);//交换两行(变换1)
double mul=a[i][i];
for(int j=i;j<=n+1;j++){
a[i][j]/=mul;//除一个数(变换2)
}
for(int k=1;k<=n;k++){
if(k==i)continue;//不能给自己减
mul=a[k][i];
for(int j=i;j<=n+1;j++){
a[k][j]-=a[i][j]*mul;//乘以一个数,再减给另一行(变换2+3)
}
}
}
return 1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n+1;j++){
scanf("%lf",&a[i][j]);
}
}
if(!gauss()){
printf("No Solution");
return 0;
}
else{
for(int i=1;i<=n;i++){
printf("%.2lf\n",a[i][n+1]);//依次输出每一个解
}
}
return 0;
}