题意
给定一个线性方程组,对其求解。
$1 \leq n \leq 100, \left | a_i \right| \leq {10}^4 , \left |b \right| \leq {10}^4 $
题解
因为之前贺题解的时候没有理解高斯-约当消元法的实际意义所以滚回来复习了。
绝对不是因为被期望 DP 撅了才来的。
贺一下题解区的讲解。
相对于传统的高斯消元,约旦消元法的精度更好、代码更简单,没有回带的过程。
约旦消元法大致思路如下:
1.选择一个尚未被选过的未知数作为主元,选择一个包含这个主元的方程。
2.将这个方程主元的系数化为1。
3.通过加减消元,消掉其它方程中的这个未知数。
4.重复以上步骤,直到把每一行都变成只有一项有系数。
我们用矩阵表示每一项系数以及结果。
提几个要点。
1.从第一项开始枚举主元,然后选取所有行中主元系数绝对值最大的哪个。方便确认无解——若该项绝对值最大的都是 0,意味着这个主元的系数全都是 0,有无穷解。
2.选取完最大的那个之后直接将最大的作为当前行,方便后续打印方案与卡常。
3.消元直接从主元 +1 项开始。因为我们知道前面的项已经被消没了,主元项减完肯定是 0,完全不用管了。
4.最后打印的时候记得让常数项除上主元的系数。
const ll maxn=105;
db f[maxn][maxn];
ll n;
bool check(db x){
if(fabs(x)<=1e-8)return 1;
return 0;
}
void solve(){
n=R;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n+1;j++){
f[i][j]=1.0*R;
}
}
for(ll i=1;i<=n;i++){
ll cur=i;
for(ll j=i+1;j<=n;j++){
if(fabs(f[j][i])>fabs(f[cur][i]))cur=j;
}
for(ll j=1;j<=n+1;j++)swap(f[i][j],f[cur][j]);
if(check(f[i][i])){
cout<<"No Solution"<<endl;
return ;
}
for(ll j=1;j<=n;j++){
if(j==i)continue;
db inv=f[j][i]/f[i][i];
for(ll k=i+1;k<=n+1;k++){
f[j][k]-=inv*f[i][k];
}
}
}
for(ll i=1;i<=n;i++){
printf("%.2lf\n",f[i][n+1]/f[i][i]);
}
return ;
}
奥义·混沌邪恶·cout+快读+printf·魔怔人
标签:系数,Luogu,高斯消,主元,leq,P3389,题解,元法 From: https://www.cnblogs.com/rnfmabj/p/luogup3389.html