LG3389 【模板】高斯消元法
题意
题目描述
给定一个线性方程组,对其求解
输入输出格式
输入格式:
第一行,一个正整数\(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)\)的算法,需要一些矩阵及行列式的知识……那么由本蒟蒻来记录一下这个算法吧!
那么假设有一个线性方程组是长这样的:
\]
emmm这就是一个很简单的三元一次方程,让我们想想常规方法该怎么做(先不谈code)
初中老师说过:我们可以加减消元或者代入消元,但是我们需要在程序里实现的时候,需要一种有规律可循的算法。所以我们选择加减消元,但用代入消元回带。
整体思路就是我们可以先在某一个式子里,用这个式子的\(x\)消去其他式子里的\(x\),然后在剩下的两个式子里再选择一个式子里的\(y\),用这个\(y\)消去最后剩下的式子里的\(y\)。那么现在最后一个方程里就只有一个未知数\(z\)了。倘若\(z\)的系数是1,那么我们就可以直接得出答案来了(别觉得这句话是废话)。
比如刚才这个方程,我们用第二个式子去消1、3式里的$x:
\]
整理之后再用第三个式子里的\(y\)消去第一个式子里的\(y\)(注意,由于第二个式子作为消元用式,所以接下来的运算不再考虑二式):
\]
那么我们发现在1式中只剩下一个未知数了,那么就可解得:
\(z=3\)
带回三式里解出
\(y=2\)
再将\(x\)、\(y\)带回最早被消掉的二式里,解得
\(x=1\)
好像这个方法再数学逻辑上讲是特别麻烦的,但是却是一个通用性强的方法qwq
那么放在程序实现上来讲,我们可以先用一个n \times (n+1)n×(n+1)的矩阵来记录每一个式子的系数以及结果。譬如上式就可以用矩阵表示成这样:
\]
左边记录系数,右边记录每个式子的结果。
那么首先我们需要用第一列中(所有的\(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_{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 【模板】高斯消元法的更多相关文章
- LG3389 「模板」高斯消元法 高斯消元
问题描述 LG3389 题解 高斯消元,是用来解\(n\)元一次方程组的算法,时间复杂度\(O(n^3)\) 这样就构造出了这个方程组的矩阵 目标就是把这个矩阵左边\(n \times n\)消为单位 ...
- 高斯消元法(Gauss Elimination)【超详解&模板】
高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. ...
- 洛谷P3389 【模板】高斯消元法
P3389 [模板]高斯消元法 题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 n 第二至 n+1行,每行 n+1 个整数,为a1,a ...
- 题解 P3389 【【模板】高斯消元法】
题解 P3389 [[模板]高斯消元法] 看到大家都没有重载运算符,那我就重载一下运算符给大家娱乐一下 我使用的是高斯-约旦消元法,这种方法是精度最高的(相对地) 一句话解释高斯约旦消元法: 通过加减 ...
- 「LuoguP3389」【模板】高斯消元法
题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 nn 第二至 n+1n+1行,每行 n+1n+1 个整数,为a_1, a_2 \cdot ...
- 洛谷——P3389 【模板】高斯消元法
P3389 [模板]高斯消元法 以下内容都可省略,直接转大佬博客%%% 高斯消元总结 只会背板子的蒟蒻,高斯消元是什么,不知道诶,看到大佬们都会了这个水题,蒟蒻只好也来切一切 高斯消元最大用途就是解多 ...
- (模板)poj2947(高斯消元法解同余方程组)
题目链接:https://vjudge.net/problem/POJ-2947 题意:转换题意后就是已知m个同余方程,求n个变量. 思路: 值得学习的是这个模板里消元用到lcm的那一块.注意题目输出 ...
- (模板)poj1681 高斯消元法求异或方程组(无解、唯一解、多解)
题目链接:https://vjudge.net/problem/POJ-1681 题意:类似于poj1222,有n×n的01矩阵,翻转一个点会翻转其上下左右包括自己的点,求最少翻转多少点能使得矩阵全0 ...
- [Luogu 3389]【模板】高斯消元法
Description 给定一个线性方程组,对其求解 Input 第一行,一个正整数 n 第二至 n+1 行,每行 n+1 个整数,为a1,a2⋯an和 b,代表一组方程.1,a2⋯an ...
随机推荐
- 大数据,why python
大数据,why python ps, 2015-12-4 20:47:46 python" title="大数据,why python">http://www.op ...
- 初识PHP(一)基础语法
一直准备学习PHP,结果前一段时间总是有事情,耽误了一阵子.现在赶快迎头赶上! 这个系列只是谈谈我对于PHP的一些看法,不是教程性质的.另外我是小白,只是写写随笔,大神求轻拍.本人学习过c .java ...
- 各版本的区别及含义(i386 、x86_64 、ppc )
1.i386:是指兼容Intel 80386处理器 x86或80x86是英代爾Intel首先开发制造的一种微处理器体系结构的泛称.該系列較早期的處理器名稱是以數字來表示,並以“86”作為結尾, ...
- Java的初始化与清理
大家都知道,Java是站在巨人的肩上成功的,它是在C&C++的基础上进一步的开发,投入面向对象开发的怀抱.Java吸取了很多以前的教训,加入自己很多独创的方式.在程序语言发展初期,许多C程序员 ...
- firefox_flash_install_on_kali
手动安装firefox的flash的步骤 1> 下载flash的tar.gz安装包 firefox http://get2.adobe.com/cn/flashplayer/otherversi ...
- 自定义Git【转】
本文转载自:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 自定义Git 在安装G ...
- UVA 11475 Extend to Palindrome(hash)题解
题意:问你最少加几个字母使所给串变成回文串. 思路:一开始打算将正序和逆序都hash,然后用提取前缀后缀的方法来找,但是RE了,debug失败遂弃之.后来发现可以直接hash,一边hash一边比较.我 ...
- 记第一场atcoder和codeforces 2018-2019 ICPC, NEERC, Northern Eurasia Finals Online Mirror
下午连着两场比赛,爽. 首先是codeforses,我和一位dalao一起打的,结果考炸了,幸亏不计rating.. A Alice the Fan 这个就是记忆化搜索一下预处理,然后直接回答询问好了 ...
- shell fold限制文件行宽
将文本的行限制到特定的宽 这个用 echo 命令发送的文本用 -w 选项分解成块. 在这个例子中,我们设定了行宽为12个字符. 如果没有字符设置,默认是80. 增加的 -s 选项将让 fold 分解到 ...
- taglist-plus 安装使用
taglist 可以查看文件中的 类,函数,变量等信息. 在.vimrc中添加: Plugin 'taglist-plus' 然后打开vim编辑器 PluginInstall 使用: 打开taglis ...