P3389 【模板】高斯消元法

题目背景

Gauss消元

题目描述

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

输入输出格式

输入格式:

第一行,一个正整数 n

第二至 n+1行,每行 n+1 个整数,为a1​,a2​⋯an​ 和 b,代表一组方程。

输出格式:

共n行,每行一个数,第 i行为 xi​ (保留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≤n≤100,∣ai​∣≤104,∣b∣≤104

sol:究竟是什么东西(感觉像小学奥数)

我们首先确定一个方程组作为例子

x-2y+3z=6
4x-5y+6z=12
7x-8y+10z=21

先将它转化为矩阵

1 -2 3 6
4 -5 6 12
7 -8 10 21

解决这个方程组

我们会希望它变成如下形式

1 0 0 a
0 1 0 b
0 0 1 c

这样就可以表示为x=a,y=b,z=cx=a,y=b,z=c

我们使用高斯消元,就要一步一步将每个未知数约去。

这种方法是以列为单位消去的

首先我们将第一列转化为1 0 0的形式

在这里要注意一下,我们往往是将这个系数绝对值最大的方程转移到被减的这一行,这样就可以减小误差

所以我们先将矩阵变成这样

7 -8 10 21
4 -5 6 12
1 -2 3 6

然后将正在处理的方程式化简,让正被处理的系数化1

1 -8/7 10/7 3
4 -5 6 12
1 -2 3 6

然后使用加减法将第二个与第三个方程组的第一个系数化0

1 -8/7 10/7 3
0 -3/7 2/7 0
0 -6/7 11/7 3

然后这时候第一列就被化简完成

同理我们化去第二行与第三行,步骤如下:

1.化简第二行

1 -8/7 10/7 3
0 1 -2/3 0
0 -6/7 11/7 3

2.用第一行减第二行×(-8/7),第三行减第二行×(-6/7)

1 0 2/3 3
0 1 -2/3 0
0 0 1 3

3.不需要化简第三行,所以直接用第一行减去第三行×2/3,第二行减去第三行×(-2/3)

1 0 0 1
0 1 0 2
0 0 1 3

最后我们就得到了一组解x=1,y=2,y=3x=1,y=2,y=3。所以高斯消元其实是运用了小学解方程组的加减法的呢。

注意是一列列消去的

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll S=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
S=S*+(ch-''); ch=getchar();
}
return (f)?(-S):(S);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar(x%+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=;
const double eps=1e-;
int n;
double a[N][N];
inline bool Gauss()
{
int i,j,k;
for(i=;i<=n;i++)
{
k=i;
for(j=i+;j<=n;j++) if(fabs(a[j][i])>fabs(a[k][i])) k=j;
//找到最大的数
if(fabs(a[k][i])<eps) return false;
if(i!=k) for(j=i;j<=n+;j++) swap(a[k][j],a[i][j]);
//对换一行或一列,属于找最大当前系数的其中一步.(这样就可以只处理当前行的系数啦!)
double Div=a[i][i];
for(j=i;j<=n+;j++) a[i][j]/=Div;
for(j=;j<=n;j++) if(j!=i)
{
Div=a[j][i];
for(k=i;k<=n+;k++)
{
a[j][k]-=a[i][k]*Div;
}
}
//把这列除这个数外都消成0
}
return true;
}
int main()
{
int i,j;
R(n);
for(i=;i<=n;i++)
{
for(j=;j<=n+;j++) scanf("%lf",&a[i][j]);
}
if(!(Gauss()))
{
puts("No Solution");
}
else
{
for(i=;i<=n;i++) printf("%.2lf\n",a[i][n+]);
}
return ;
}
/*
input
3
1 3 4 5
1 4 7 3
9 3 2 2
output
-0.97
5.18
-2.39
*/

附上更加符合上面教程的代码(完全按照上面写的)

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const double eps=1e-;
const int N=;
int n;
double a[N][N],b[N];
inline void Debug()
{
int i,j;
for(i=;i<=n;i++)
{
for(j=;j<=n;j++) printf("%.2lf ",a[i][j]);
printf("%.2lf",b[i]);
puts("");
}
puts("");
}
inline void Gauss(int n)
{
int i,j,k;
double Div;
for(i=;i<=n;i++)
{
int Pos=i;
for(j=i+;j<=n;j++) if(fabs(a[Pos][i])<fabs(a[j][i])) Pos=j;
if(fabs(a[Pos][i])<eps)
{
puts("No Solution");
exit();
}
if(Pos!=i)
{
swap(a[i],a[Pos]); swap(b[i],b[Pos]);
}
Div=a[i][i];
for(j=i;j<=n;j++) a[i][j]/=Div; b[i]/=Div;
for(j=;j<=n;j++) if(j!=i)
{
Div=a[j][i];
for(k=i;k<=n;k++)
{
a[j][k]-=Div*a[i][k];
}
b[j]-=Div*b[i];
}
// Debug();
}
}
int main()
{
int i,j;
R(n);
for(i=;i<=n;i++)
{
for(j=;j<=n;j++) scanf("%lf",&a[i][j]); scanf("%lf",&b[i]);
}
Gauss(n);
for(i=;i<=n;i++) printf("%.2lf\n",b[i]);
return ;
}
/*
input
3
1 3 4 5
1 4 7 3
9 3 2 2
output
-0.97
5.18
-2.39
*/

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

  1. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  2. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

  3. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  4. 【AC自动机】洛谷三道模板题

    [题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...

  5. 洛谷-P5357-【模板】AC自动机(二次加强版)

    题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,还是要解决跳fail边产生的重复访问,但 ...

  6. 洛谷.1919.[模板]A*B Problem升级版(FFT)

    题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 ...

  7. 洛谷.3803.[模板]多项式乘法(FFT)

    题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. 5.4 又看了一遍,这个也不错. 2019.3.7 叕看了一遍,推荐这个. #inclu ...

  8. 洛谷.3803.[模板]多项式乘法(NTT)

    题目链接:洛谷.LOJ. 为什么和那些差那么多啊.. 在这里记一下原根 Definition 阶 若\(a,p\)互质,且\(p>1\),我们称使\(a^n\equiv 1\ (mod\ p)\ ...

  9. 洛谷P3385 [模板]负环 [SPFA]

    题目传送门 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个 ...

  10. [洛谷P3806] [模板] 点分治1

    洛谷 P3806 传送门 这个点分治都不用减掉子树里的了,直接搞就行了. 注意第63行 if(qu[k]>=buf[j]) 不能不写,也不能写成>. 因为这个WA了半天...... 如果m ...

随机推荐

  1. face recognition[Euclidean-distance-based loss][Center Face]

    本文来自<A Discriminative Feature Learning Approach for Deep Face Recognition>,时间线为2016年.采用的loss是C ...

  2. Winform开发框架中的内容及文档管理模块功能介绍

    在开发项目的时候,我们有一些场景需要编辑一些HTML文档,作为内容发布系统的一部分,有时候也需要对一些文档如WORD文档进行编辑管理,这样需要我们对这些内容及文档进行合适的管理.本文主要介绍在WInf ...

  3. H5 20-属性选择器上

    20-属性选择器上 --> 我是段落1 我是段落2 我是段落3 我是段落4 我是段落5 <!DOCTYPE html> <html lang="en"> ...

  4. hibernate在写cfg配置文件自动创建表时报错org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister

    在用hibernate框架时,写cfg文件,想自动生成表时,一般写<property name="hibernate.hbm2ddl.auto">create</ ...

  5. java总结:double取两位小数的多种方法

    1.方法一 四舍五入: import java.math.BigDecimal; double f = 111231.5585; BigDecimal b = new BigDecimal(f); d ...

  6. linux的nohup命令

    linux的nohup命令的用法. - runfox545 - 博客园https://www.cnblogs.com/allenblogs/archive/2011/05/19/2051136.htm ...

  7. Visual Studio 2010 Shortcuts

    Uploaded by ProNotion, updated on 11/28/2013 by jmb Platform: Windows/ English  PDF    Print   Hide ...

  8. C\C++学习笔记 3

    C++记录7 函数指针: 函数名为地址, 地址指的是在机器指令存储的地址. double func(int line){ reture line*3.5;} void f(int line, doub ...

  9. Thread类相关方法

    线程对象 每一个线程都是和类Thread的实例相关联的.在Java中,有两种基本的使用Thread对象的方式,可用来创建并发性程序.  1.在应用程序需要发起异步任务的时候,只要生成一个Thread对 ...

  10. 校园电商项目3(基于SSM)——配置Maven

    步骤一:添加必要文件夹 先在src/main/resources下添加两个文件夹 接着在webapp文件夹下添加一个resources文件夹存放我们的静态网页内容 WEB-INF里的文件是不会被客户端 ...