P3389 【模板】高斯消元法
以下内容都可省略,直接转大佬博客%%%
高斯消元总结
只会背板子的蒟蒻,高斯消元是什么,不知道诶,看到大佬们都会了这个水题,蒟蒻只好也来切一切
高斯消元最大用途就是解多元一次方程组——引自某大佬原话
的确是这样的,那么如何去做呢?
类比二元一次方程组:
$a_1x+b_1y=c_1$
$a_2x+b_2y=c_2$
emmm,怎么做呢?消去一项!嗯。
也就是把第$i$个方程的第$i$项变成1
$frac{a_1}{a_1}x+frac{b_1}{a_1}y=frac{c_1}{a_1}$
也就是$x+frac{b_1}{a_1}y=frac{c_1}{a_1}$
再用这个式子消去第$i+1$到$n$方程的第$i$项,
$frac{a_2}{a_2}x+frac{b_2}{a_2}y=frac{c_2}{a_2}$
也就是$x+frac{b_2}{a_2}y=frac{c_2}{a_2}$
用这一项减去上一项$0+(frac{b_2}{a_2}-frac{b_1}{a_1})y=frac{c_2}{a_2}-frac{c_1}{a_1}$
由于将每一项的系数都化为一比较麻烦,我们尝试直接消去那一项
$a_1x+b_1y=c_1$
$a_2x+b_2y=c_2$
第二项变成$a_2 imes frac{a_1}{a_2}x+b_2 imes frac{a_1}{a_2}y=c_2 imes frac{a_1}{a_2}$
消去第一项$(a_2 imes frac{a_1}{a_2}-a_1)x+(b_2 imes frac{a_1}{a_2}-b_1)y=c_2 imes frac{a_1}{a_2}-c_1$
这样是可行的,同样是把第二个方程组的第一项系数化为$0$
for(int i=1;i<=n;i++){ if(!a[i][i]) return puts("No Solution "),0; for(int j=i+1;j<=n;j++) for(int k=n+1;k>=i;k--) a[j][k]=a[j][k]*a[i][i]/a[j][i]-a[i][k];
}//消元
不过大佬们都是这样写的,见代码:
$a_1x+b_1y=c_1$
$(a_2-frac{a_2}{a_1} imes a_1)x+(b_2-frac{a_2}{a_1} imes b_1)y=c_2-frac{a_2}{a_1} imes c_1$
貌似这才是正确的操作,相当于把第一个方程同除以$a_1$,第二个方程减去$a_2 imes...$
回代过程略。。。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; double a[205][205],x[205]; int n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)//n个方程 for(int j=1;j<=n+1;j++)//n项以及最后c scanf("%lf",&a[i][j]); for(int i=1;i<=n;i++){//枚举每一方程 if(!a[i][i]) return puts("No Solution "),0; for(int j=i+1;j<=n;j++) for(int k=n+1;k>=i;k--) a[j][k]-=a[i][k]*a[j][i]/a[i][i]; }//消元 for(int i=n;i;i--){ x[i]=a[i][n+1]; for(int j=n;j>i;j--) x[i]-=a[i][j]*x[j]; x[i]/=a[i][i]; }//回代 for(int i=1;i<=n;i++) printf("%.2lf ",x[i]); return 0; }