题意

题目描述

给定一个线性方程组,对其求解

输入输出格式

输入格式:

第一行,一个正整数\(n\)

第二至\(n+1\)行,每行\(n+1\)个整数,为\(a_1, a_2 \cdots a_n\)和\(b\),代表一组方程。

输出格式:

共n行,每行一个数,第\(i\)行为\(x_i\)(保留2位小数)

如果不存在唯一解,在第一行输出"No Solution".

输入输出样例

输入样例#1:

3

1 3 4 5

1 4 7 3

9 3 2 2

输出样例#1:

-0.97

5.18

-2.39

说明

\(1 \leq n \leq 100, \left | a_i \right| \leq {10}^4 , \left |b \right| \leq {10}^4\)

分析

参照_皎月半洒花的题解。

emmmm这个消元方式其实严格来说是可行性算法……而不是优化性算法……不过话说由于我太蒟蒻了,所以并不知道什么更优的算法(#滑稽)

嗯,其实这个算法是\(O(n^3)\)的算法,需要一些矩阵及行列式的知识……那么由本蒟蒻来记录一下这个算法吧!

那么假设有一个线性方程组是长这样的:

\[\begin{Bmatrix} 3x & + & 2y &+& z &=&10 \\5x & + & y &+& 6z &=&25 \\2x & + & 3y &+& 4z &=&20\end{Bmatrix}
\]

emmm这就是一个很简单的三元一次方程,让我们想想常规方法该怎么做(先不谈code)

初中老师说过:我们可以加减消元或者代入消元,但是我们需要在程序里实现的时候,需要一种有规律可循的算法。所以我们选择加减消元,但用代入消元回带。

整体思路就是我们可以先在某一个式子里,用这个式子的\(x\)消去其他式子里的\(x\),然后在剩下的两个式子里再选择一个式子里的\(y\),用这个\(y\)消去最后剩下的式子里的\(y\)。那么现在最后一个方程里就只有一个未知数\(z\)了。倘若\(z\)的系数是1,那么我们就可以直接得出答案来了(别觉得这句话是废话)。

比如刚才这个方程,我们用第二个式子去消1、3式里的$x:

\[\begin{Bmatrix} 0\times x & + & \frac{7}{5}y &+& (-\frac{13}{5}z) &=&-5 \\5x & + & y &+& 6z &=&25 \\0\times x & + & \frac{13}{5}y &+& \frac{8}{5}z &=&10\end{Bmatrix}
\]

整理之后再用第三个式子里的\(y\)消去第一个式子里的\(y\)(注意,由于第二个式子作为消元用式,所以接下来的运算不再考虑二式):

\[\begin{Bmatrix}0\times y &+& (-\frac{225}{65}z) &=&-\frac{135}{13} \\ \frac{13}{5}y &+& \frac{8}{5}z &=&10\end{Bmatrix}
\]

那么我们发现在1式中只剩下一个未知数了,那么就可解得:

\(z=3\)

带回三式里解出

\(y=2\)

再将\(x\)、\(y\)带回最早被消掉的二式里,解得

\(x=1\)

好像这个方法再数学逻辑上讲是特别麻烦的,但是却是一个通用性强的方法qwq

那么放在程序实现上来讲,我们可以先用一个n \times (n+1)n×(n+1)的矩阵来记录每一个式子的系数以及结果。譬如上式就可以用矩阵表示成这样:

\[\begin{Bmatrix} 3& 2 & 1 &|& 10 \\5 & 1 & 6 &|& 25 \\2 & 3 & 4 &|&20\end{Bmatrix}
\]

左边记录系数,右边记录每个式子的结果。

那么首先我们需要用第一列中(所有的\(x\)中)系数最大的来消其他两个式子。而这里为了方便起见,我们将这个选中的系数置为1,方便上例中地不断带回原式的操作(这样在回带的时候就可以不考虑原本的系数了)。

由于最多也只能用double型存储,所以必然会有精度误差。但如果我们每次都选用最大系数的来消掉其他系数,就可以最大程度地来减小误差。以下是一种不严谨地、适合意会的证明(选读):

假设我们现在在处理第nn个未知数,此时在众多的未知数nn中,他们的系数分别是\(k_1 k_2 k_3 k_ 4\dots k_m\),那么考虑,在选完\(k_i\)之后,下面我们要进行的是把\(k_i\)消成1。那么此时对于第ii行的其他的系数以及结果我们都要除以\(k_i\) 。

之后呢?之后我们要进行的操作是用这个式子来消掉其他式子里的该未知数啊qwq。如果要这么操作肯定会让其他式子别的未知数的系数,减去当前式子的别的未知数的系数乘上某个值(事实上假设选择含\(k_i\)的式子,则对于每个式子\(j\)而言,每个系数减去当前系数的倍数,这个倍数应该为\(k_j\)那么这样看来,对于当次用来消元的式子的每个系数\(q_{i1}q_{i2}q_{i3}q_{i4} ……q_{iw}\) (假设当前元的系数是\(q_{i1}\)而言,对于每一个其他式子的该项系数\(q_{jw}\),都需要让\(q_{jw}\)变成

\[q_{jw}-\frac{q_{j1}}{q_{i1}} \times q_{iw}
\]

那么我们观察这个式子,\(q_{i1}\)越大,\(\frac{q_{j1}}{q_{i1}}\)期望越小,那么我们考虑,这个值越小,我们就约可以把它看作一个“基本单位”。从而我们就使得减出来的值失精程度越低,最后即可保证数据是从期望上来讲最精确。

嗯,讲的很麻烦,大家挑重点看吧(或者只看最后一个自然段)

在置为1之后,我们需要来用这个式子去消其他的式子(别忘了每个式子的结果也要消)。那么在最后,我们只需要将这个矩阵的最右下角(也就是最后一个元的实际值)不断回带即可。

时间复杂度\(O(n^3)\)

代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef long long ll;
co double eps=1e-7;
double map[111][111],ans[111];
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
int n=read<int>();
for(int i=1;i<=n;++i)
for(int j=1;j<=n+1;++j) read(map[i][j]);
for(int i=1;i<=n;++i){
int r=i;
for(int j=i+1;j<=n;++j)
if(fabs(map[r][i])<fabs(map[j][i])) r=j;
if(fabs(map[r][i])<eps){
puts("No Solution");
return 0;
}
if(i!=r) std::swap(map[i],map[r]);
double div=map[i][i];
for(int j=i;j<=n+1;++j) map[i][j]/=div;
for(int j=i+1;j<=n;++j){
div=map[j][i];
for(int k=i;k<=n+1;++k) map[j][k]-=map[i][k]*div;
}
}
ans[n]=map[n][n+1];
for(int i=n-1;i>=1;--i){
ans[i]=map[i][n+1];
for(int j=i+1;j<=n;++j) ans[i]-=(map[i][j]*ans[j]);
}
for(int i=1;i<=n;++i) printf("%.2lf\n",ans[i]);
return 0;
}

LG3389 【模板】高斯消元法的更多相关文章

  1. LG3389 「模板」高斯消元法 高斯消元

    问题描述 LG3389 题解 高斯消元,是用来解\(n\)元一次方程组的算法,时间复杂度\(O(n^3)\) 这样就构造出了这个方程组的矩阵 目标就是把这个矩阵左边\(n \times n\)消为单位 ...

  2. 高斯消元法(Gauss Elimination)【超详解&模板】

    高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. ...

  3. 洛谷P3389 【模板】高斯消元法

    P3389 [模板]高斯消元法 题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 n 第二至 n+1行,每行 n+1 个整数,为a1​,a ...

  4. 题解 P3389 【【模板】高斯消元法】

    题解 P3389 [[模板]高斯消元法] 看到大家都没有重载运算符,那我就重载一下运算符给大家娱乐一下 我使用的是高斯-约旦消元法,这种方法是精度最高的(相对地) 一句话解释高斯约旦消元法: 通过加减 ...

  5. 「LuoguP3389」【模板】高斯消元法

    题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 nn 第二至 n+1n+1行,每行 n+1n+1 个整数,为a_1, a_2 \cdot ...

  6. 洛谷——P3389 【模板】高斯消元法

    P3389 [模板]高斯消元法 以下内容都可省略,直接转大佬博客%%% 高斯消元总结 只会背板子的蒟蒻,高斯消元是什么,不知道诶,看到大佬们都会了这个水题,蒟蒻只好也来切一切 高斯消元最大用途就是解多 ...

  7. (模板)poj2947(高斯消元法解同余方程组)

    题目链接:https://vjudge.net/problem/POJ-2947 题意:转换题意后就是已知m个同余方程,求n个变量. 思路: 值得学习的是这个模板里消元用到lcm的那一块.注意题目输出 ...

  8. (模板)poj1681 高斯消元法求异或方程组(无解、唯一解、多解)

    题目链接:https://vjudge.net/problem/POJ-1681 题意:类似于poj1222,有n×n的01矩阵,翻转一个点会翻转其上下左右包括自己的点,求最少翻转多少点能使得矩阵全0 ...

  9. [Luogu 3389]【模板】高斯消元法

    Description 给定一个线性方程组,对其求解 Input 第一行,一个正整数 n 第二至 n+1 行,每行 n+1 个整数,为a1,a2⋯an和 b,代表一组方程.1​​,a​2​​⋯a​n​ ...

随机推荐

  1. 忘记oracle的sys用户密码怎么修改以及Oracle 11g 默认用户名和密码

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  2. [one day one question] iphone6 plus h5页面滑动莫名卡

    问题描述: iphone6 plus h5页面滑动莫名卡,这怎么破? 解决方案: 比较奇葩的问题,在找不到任何问题的情况下,可以考虑在下发现的解决方案,html,body未添加height: 100% ...

  3. 前端学习笔记之CSS过渡模块

    阅读目录 一 伪类选择器复习 二 过渡模块的基本使用 三 控制过渡的速度transition-timing-function 四 过渡模块连写 一 伪类选择器复习 注意点: #1 a标签的伪类选择器可 ...

  4. Python面试题目之打乱打乱有序列表

    # 要求打乱一个有序列表 # 待处理列表 L1 = [11,22,33,44,55,66,77,] 方法: # 引入random模块,该模块的shuffle方法见下图 import random L1 ...

  5. [Microsoft][ODBC Microsoft Access Driver] 参数不足,期待是 1

    真tm坑. QString execStr = QString("SELECT * FROM [Log] WHERE [username]=\"yyy\" ") ...

  6. 在iframe外层head中插入link

    let src = 'abc.css?v='+Math.random(); let link = window.parent.document.createElement('link'); link. ...

  7. 创建 shiny 应用程序

    R 本身是一个优秀的数据分析和数据可视化平台.然而,我们通常不会将 R 和分析脚本提供给客户,让客户自己运行.数据分析的结果不仅可以在 HTML 网页.PDF 文档或 Word 文档中显示,还可以呈现 ...

  8. Bridge(桥接)

    意图: 将抽象部分与它的实现部分分离,使它们都可以独立地变化. 适用性: 你不希望在抽象和它的实现部分之间有一个固定的绑定关系.例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换. 类 ...

  9. appium+pytest+allure+jenkins 如何实现多台手机连接

    使用appium可以实现app自动化测试,我们之前是连接一台手机去运行,如何同时连接多台手机呢?很多人可能想到的是多线程(threading).今天分享一种比多线程更简单的方法,虽然不是多台手机同时运 ...

  10. Leetcode 18

    class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int ta ...