洛谷 P3389 【模板】高斯消元法(数论)

传送门


高斯消元

什么叫高斯消元?

就是解多元方程组的一种方法。

给你n个方程组,包含着n个未知数,告诉你每一个方程中的每一个未知数的系数和常数项。

怎么解?

和数学上差不多,把第一个方程保留第一个未知数(设系数为k),把第二个到第n个方程的第一个未知数的系数化为-k,用加减消元即可。

以此类推,枚举到第i个方程保留第i个未知数的系数k(i前面的未知数系数已经化为0),把第i+1到第n个方程的第i个未知数的系数化为-k,加起来消元。

最后就会变成如下形式:

K1*X1+K2*X2+K3*X3+……+Kn*Xn=Kn+1

0*X1+K2'*X2+K3'*X3+……+Kn'*Xn=Kn+1'

………………………………………………

0*X1+0*X2+0*X3+……+0*Xn-1+Kn*Xn=Kn+1

这样就可以从第n个方程往前推,一步步解出所有的未知数。

什么情况有多个解?

当推到某个方程(设为第i个)出现0*Xi=Kn+1

则Xi可以为任意实数。

怎么保证精度?

保证第i个方程Xi的系数最大。(证明略)

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<iomanip>
 7 using namespace std;
 8 int n;
 9 double a[105][105],ans[105];
10 int main()
11 {
12     cin>>n;
13     for(int i=1;i<=n;i++){
14         for(int j=1;j<=n;j++){
15             cin>>a[i][j];
16         }
17         cin>>a[i][n+1];
18     }
19     for(int i=1;i<=n;i++){
20         int r=i;
21         for(int j=i+1;j<=n;j++){
22             if(fabs(a[r][i])<fabs(a[j][i])) r=j;
23         }
24         if(i!=r) for(int j=i;j<=n+1;j++) swap(a[i][j],a[r][j]);
25         for(int j=i+1;j<=n;j++){
26             for(int k=i+1;k<=n+1;k++){
27                 a[j][k]=a[j][k]-a[j][i]/a[i][i]*a[i][k];
28             }
29             a[j][i]=0;
30         }
31     }
32     for(int i=n;i>=1;i--){
33         if(a[i][i]==0){
34             cout<<"No Solution";
35             return 0;
36         }
37         ans[i]=a[i][n+1]/a[i][i];
38         for(int j=1;j<i;j++){
39             a[j][n+1]-=a[j][i]*ans[i];
40         }
41     }
42     for(int i=1;i<=n;i++) cout<<fixed<<setprecision(2)<<ans[i]<<endl;
43     return 0;
44 }

 

posted @ 2020-10-30 20:47  尹昱钦  阅读(136)  评论(0编辑  收藏  举报