Luogu P3389 高斯消元
https://www.luogu.com.cn/problem/P3389
主元消元法【模板】
高斯消元是解决多元线性方程组的方法,再学习它之前,先引入一个东西——行列式
行列式的性质:
这里我们只说其中的两条:
①行列式中的一行,加上另一行的\(k\)倍,行列式的值不变
②交换行列式的两行,行列式的值会变为原来的相反数
每一个有唯一解的线性方程,都拥有一个与其对应的行列式
//如果想详细学习行列式,可以自行上网百度~
目的:为了方便求解,利用①性质,我们可以把它消成上三角行列式(矩阵的对角线的左下方都是\(0\)),其实通俗来讲,就是平时我们学的加减消元法
具体步骤:
①枚举\(1-n\)行
②用第i行的第i列(对角线上的数)来消\(i+1-n\)行的第\(i\)列数,即:将这些数都加上\(k\times c[i][i]\;\;(k=-\frac{c[j][i]}{c[i][i]})\)
这里必须要注意,\(c[i][i]\)不能是\(0\),导致没有意义。所以在算倍数k之前,要保证\(c[i][i]≠0\),即从\(i-n\)行中找到一个数,使得\(c[j][i]≠0\),然后将这两个行的数交换过来即可
根据行列式性质②,行列式的值要变号,但这里我们是在求方程组,不用管行列式值符号的问题
③然后,自下向上递推。从而求出每一个未知数的解
代码:
void gauss()
{
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
if(fabs(c[j][i])>1e-8)
//找到大于0的除
{
if(j==i)break;
for(int l=1;l<=n+1;l++)
swap(c[j][l],c[i][l]);
break;
}
if(fabs(c[i][i])<=1e-8)continue;
//如果这列已经全是0了,不必继续消了
for(int j=i+1;j<=n;j++)
{
double k=c[j][i]/c[i][i];
for (int l=1;l<=n+1;l++)
c[j][l]=c[j][l]-c[i][l]*k;
//k(倍数),把这列的数都消成0
}
}
}
但是这种方法可能会存在精度的问题,算\(k\)(倍数)时出现误差
如何提高精度?
主元消元法
假设现在有个数\(p\),还有两个数\(10^5,10^{-5}\)
那么\(p\)除以哪个数,分到的小数位数(精度)越高呢?
显然,是\(10^5\)。那么根据我们推导的结论,除数绝对值越大越好
然后我们仔细观察朴素消元的代码
会惊奇的发现只有一行对精度会有影响:
double k=c[j][i]/c[i][i];
根据我们刚刚推导的结论,\(c[i][i]\)绝对值越大,精度越高
因此,我们只需把朴素代码中的找不为\(0\)的数改成找绝对值最大的数即可
void gauss()
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(fabs(c[j][i])>fabs(c[i][i]))//找最大值
{
for(int k=1;k<=n+1;k++)
{
swap(c[j][k],c[i][k]);
}
}
}
if(fabs(c[i][i])<=1e-8)continue;//若全为0,不必继续消
for(int j=i+1;j<=n;j++)
{
double t=c[j][i]/c[i][i];
for(int k=1;k<=n+1;k++)
{
c[j][k]=c[j][k]-t*c[i][k];
}
}
}
}
这样我们就大大提高了算法的精度
还剩最后一个问题:如何判断有多组解的情况?
只需判断某一行消完后是否全为\(0\)即可(自己稍微想想即可)
详见完整代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=20;
int n;
double b[N][N],c[N][N],res[N];
void gauss()
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(fabs(c[j][i])>fabs(c[i][i]))
{
for(int k=1;k<=n+1;k++)
{
swap(c[j][k],c[i][k]);
}
}
}
if(fabs(c[i][i])<=1e-8)continue;
for(int j=i+1;j<=n;j++)
{
double t=c[j][i]/c[i][i];
for(int k=1;k<=n+1;k++)
{
c[j][k]=c[j][k]-t*c[i][k];
}
}
}
}
int main()
{
scanf("%d",&n);
for(int a=1;a<=n;a++)
for(int b=1;b<=n+1;b++)
{
scanf("%lf",&c[a][b]);
}
guass();
for(int i=1;i<=n;i++)
{
bool fail=true;
for(int j=1;j<=n+1;j++)
{
if(c[i][j])
{
fail=false;
break;
}
}
if(fail)//若某行的系数全为0,则说明无唯一解
{
puts("No Solution");
return 0;
}
}
for(int i=n;i>=1;i--)
{
double t=0;
for(int j=i+1;j<=n;j++)
{
t=t+res[j]*c[i][j];
}
res[i]=(c[i][n+1]-t)/c[i][i];
}
for(int i=1;i<=n;i++)printf("%.2lf\n",res[i]);
return 0;
}
Luogu P3389 高斯消元的更多相关文章
- 【Luogu】P3389高斯消元模板(矩阵高斯消元)
题目链接 高斯消元其实是个大模拟qwq 所以就着代码食用 首先我们读入 ;i<=n;++i) ;j<=n+;++j) scanf("%lf",&s[i][j]) ...
- 洛谷P3389 高斯消元 / 高斯消元+线性基学习笔记
高斯消元 其实开始只是想搞下线性基,,,后来发现线性基和高斯消元的关系挺密切就一块儿在这儿写了好了QwQ 先港高斯消元趴? 这个算法并不难理解啊?就会矩阵运算就过去了鸭,,, 算了都专门为此写个题解还 ...
- luogu P2962 [USACO09NOV]灯Lights 高斯消元
目录 题目链接 题解 题目链接 luogu P2962 [USACO09NOV]灯Lights 题解 可以折半搜索 map合并 复杂度 2^(n / 2)*logn 高斯消元后得到每个点的翻转状态 爆 ...
- 【Luogu】P3211XOR和路径(高斯消元)
题目链接 唉我个ZZ…… 首先考虑到异或是可以每一位分开算的 好的以后再碰见位运算题我一定先往按位开车上想 然后设f[i]为从i点出发到终点是1的概率 高斯消元解方程组即可. #include< ...
- 【Luogu】P4035球形空间产生器(高斯消元)
题目链接 水比题,把圆方程展开减一下把平方都减掉半径的平方也减掉,高斯消元即可. 然后我只输出两位小数,爆了两次零.我好菜啊. #include<cstdio> #include<c ...
- 【Luogu】P2447外星千足虫(高斯消元)
题目链接 高斯消元解%2意义下的方程,Bitset优化一下. 在消的过程中就能顺便把有解的第一问求出来,记录一下访问过的最大行. #include<cstdio> #include< ...
- 【Luogu】P3317重建(高斯消元+矩阵树定理)
题目链接 因为这个专门跑去学了矩阵树定理和高斯消元qwq 不过不是很懂.所以这里只放题解 玫葵之蝶的题解 某未知dalao的矩阵树定理 代码 #include<cstdio> #inclu ...
- Luogu P5027 【Barracuda】(高斯消元)
祭一下第一道独立做出来的高斯消元(虽然在各大佬看来都是水题...) 首先这道题给了你n+1个一次方程,n个未知数 其中有一个方程是错误的 求解在合法的前提下最大的未知数是多少... 显然高斯消元... ...
- Luogu P2447 [SDOI2010]外星千足虫 高斯消元
链接 给出的条件是异或类型的方程,可以直接用bitset优化高斯消元. 至于求K,在高斯消元时记录用到的最大的方程的编号即可. 代码: // luogu-judger-enable-o2 #inclu ...
随机推荐
- HTML学习过程-(1)
记录我HTML的学习 (1) 最开始学习html是在因为在听北京理工大学教授讲的网络公开课上.当时老师讲的是网络爬虫,因为要爬取特定网页的信息,需要借助[正则表达式](https://baike.ba ...
- 详解 List接口
本篇博文所讲解的这两个类,都是泛型类(关于泛型,本人在之前的博文中提到过),我们在学习C语言时,对于数据的存储,用的差不多都是数组和链表. 但是,在Java中,链表就相对地失去了它的存在价值,因为Ja ...
- EasyPoi 导入导出Excel时使用GroupName的踩坑解决过程
一.开发功能介绍: 简单的一个excel导入功能 二.Excel导入模板(大致模板没写全): 姓名 性别 生日 客户分类 联系人姓名 联系人部门 备注 材料 综合 采购 张三 男 1994/05/25 ...
- GitHub 热点速览 Vol.17:在?各家视频会员要不要?
作者:HelloGitHub-小鱼干 摘要:经济实用,用作上周的 GitHub 热点的横批再合适不过.先不说 GitHub Trending 上不止一个的会员共享项目,免你找好友刷脸要会员,这项目实在 ...
- VRRP概念、工作原理
VRRP是一种路由容错协议,也可以叫做备份路由协议,可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台. 控制虚拟路由器 IP 地址的 VRRP 路由器称为主路由器, 它负责转发 ...
- ElasticSearch 镜像 & 安装 & 简易集群
目录 ES镜像 JDK镜像 安装 1. 安装JDK 2. 解压安装ES 3. 配置 4. 新建用户 5. 启动 踩坑 1. root启用报错 2. max file descriptors [4096 ...
- Java中的小数运算与精度损失
float.double类型的问题 我们都知道,计算机是使用二进制存储数据的.而平常生活中,大多数情况下我们都是使用的十进制,因此计算机显示给我们看的内容大多数也是十进制的,这就使得很多时候数据需要在 ...
- AndroidStudio提高编译速度的建议
1.使用最新的Android gradle插件 Google tools team一直致力于提高android studio的编译速度,使用最新的gradle插件可以搞编译速度 在Android Gr ...
- 【shell】Shell变量基础及深入
1. 什么是变量 变量就是用一个固定的字符串(也可能是字符数字等的组合),替代更多更复杂的内容,这个内容里可能还会包含变量和路径,字符串等其他内容. 变量的定义是存在内存中. x=1 y=2 2. 变 ...
- 【linux题目】第一关
详细的解答:https://github.com/Zoe233/Linux/blob/master/[题目]5.Linux了解程度测试题解析.ipynb 1. 创建一个目录/data 解答: mkdi ...