Guass消元

约旦·高斯消元法 求线性方程组

我们用一个\(n*(n+1)\)的矩阵存储线性方程组各项系数和零次项系数。

  1. 每一次找到一个未知数系数最大的方程,交换当前行方程和该方程,并将其他行该未知数的系数化为零。
  2. 重复n次即可。
  3. 最后第\(a[i][i]\)个数就是第i个未知数的系数,\(a[i][n+1]\)是等式右侧的数,用后者除以前者即可。
  • 当化第i个方程时,若找到所有方程的最大值为零,即都为零,则无解。
  • 当一个未知数在多于0个少于n个方程中有系数,该未知数为自由元,线性方程组有无数组解。

洛谷P3389

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cmath>
using namespace std;
inline int read(){
int x=0,w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=105;
double a[maxn][maxn];
int n;
inline void work(){
n=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)a[i][j]=(double)read();
for(int i=1;i<=n;i++){
int mx=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[j][i])>fabs(a[mx][i]))mx=j;
swap(a[i],a[mx]);
if(!a[i][i])return (void)puts("No Solution");
for(int j=1;j<=n;j++){
if(j==i)continue;
double tmp=a[j][i]/a[i][i];
for(int k=i+1;k<=n+1;k++)
a[j][k]-=a[i][k]*tmp;
}
}
for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]/a[i][i]);
}
}
signed main(){
star::work();
return 0;
}

让我们再做一道不那么板子的题目:

P4035 球形空间产生器

简述题意,我们需要求一个n维向量\((x_1,x_2,\dots,x_n)\)使得对于每个i都满足\(\sum_{j=1}^{n}(a_{i,j}-x_j)^2=dis\),

其中\(dis\)为未知常数。

所以我们考虑消去这个\(dis\):

我们将相邻的i的方程做差得到:

\[\sum_{j=1}^{n}a_{i+1,j}^2-a_{i,j}^{2}-2x_j(a_{i+1,j}-a_{i,j})=0
\]

然后将常数项与未知数剥离:

\[\sum_{j=1}^{n}2x_j(a_{a+1,j}-a_{i,j})=\sum_{j=1}^na_{i+1,j}^2-a_{i,j}^2
\]

解线性方程组即可。

题目给定有解。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cmath>
using namespace std;
const int maxn=12;
double b[maxn][maxn],a[maxn][maxn];
int n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n;j++)scanf("%lf",&b[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=(b[i][j]-b[i+1][j])*2;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
a[i][n+1]+=b[i][j]*b[i][j]-b[i+1][j]*b[i+1][j];
}
for(int i=1;i<=n;i++){
int mx=i;
for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[mx][i]))mx=j;
swap(a[mx],a[i]);
for(int j=1;j<=n;j++){
if(j==i)continue;
double tmp=a[j][i]/a[i][i];
for(int k=i+1;k<=n+1;k++)
a[j][k]-=a[i][k]*tmp;
}
}
for(int i=1;i<=n;i++)printf("%.3lf ",a[i][n+1]/a[i][i]);
return 0;
}

求行列式的值

依据行列式的性质,我们用高斯消元将行列式转变为下三角矩阵,行列式的值就为对角线上各数的积。

  • 当行列式其中两行成比例时行列式值为零。所以我们在高斯消元的时候发现只要有一列找不到有值的数就是这种情况,直接返回0即可。
  • 一般来说,求行列式有可能加模数或者行列式值很大,我们在除的时候用逆元搞就行了。
inline int Guass(int *a){
int ans=1;
for(int i=1;i<=n;i++){
int pos=0;
for(int j=i;j<=n;j++)if(a[j][i]){pos=j;break;}
if(!pos)return 0;
if(pos!=i)swap(a[pos],a[i]);
int inv=fpow(a[i][i],mod-2,mod);//快速幂
for(int j=i+1;j<=n;j++){
if(a[j][i]){
ans=ans*inv%mod;
for(int k=i+1;k<=n;k++)
a[j][k]=((a[j][k]*a[i][i]%mod-a[i][k]*a[j][i]%mod)%mod+mod)%mod;
a[j][i]=0;
}
}
}
for(int i=1;i<=n;i++)ans=ans*a[i][i]%mod;
return ans;
}

求逆矩阵

根据rsk大佬的课,我们可以知道矩阵求逆有一个方法是:

  1. 给原矩阵右边接一个等大的单位矩阵。
  2. 高斯消元,将原矩阵转为单位矩阵。
  3. 右侧矩阵即为所求。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cmath>
#define int long long
using namespace std;
inline int read(){
int x=0,w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=405,mod=1e9+7;
int n,a[maxn][maxn<<1];
inline int fpow(int a,int b){
int ans=1;
for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;
return ans;
}
inline void work(){
n=read();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)a[i][j]=read();
a[i][n+i]=1;
}
for(int i=1;i<=n;i++){
int mx=i;
for(int j=i+1;j<=n;j++)
if(a[mx][i]<a[j][i])mx=j;
swap(a[mx],a[i]);
if(!a[i][i])return (void)puts("No Solution");
int inv=fpow(a[i][i],mod-2);
for(int j=1;j<=n;j++){
if(j==i)continue;
for(int tmp=a[j][i]*inv%mod,k=1;k<=n*2;k++)//k可以从i+1开始,不会更新下三角
a[j][k]=(a[j][k]-a[i][k]*tmp%mod+mod)%mod;
}
} for(int i=1;i<=n;i++){
for(int tmp=fpow(a[i][i],mod-2),j=1;j<=n;j++)
printf("%lld ",a[i][j+n]*tmp%mod);
puts("");
}
}
}
signed main(){
star::work();
return 0;
}

Guass消元总结的更多相关文章

  1. UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  2. BZOJ 3270 && BZOJ 1778 (期望DP && 高斯消元)

    BZOJ 3270 :设置状态为Id(x,y)表示一人在x,一人在y这个状态的概率. 所以总共有n^2种状态. p[i]表示留在该点的概率,Out[i]=(1-p[i])/Degree[i]表示离开该 ...

  3. hdu 5833 Zhu and 772002 高斯消元

    Zhu and 772002 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test ...

  4. hdu4418(概率dp + 高斯消元)

    应该是一个入门级别的题目. 但是有几个坑点. 1. 只选择x能到达的点作为guass中的未知数. 2. m可能大于n,所以在构建方程组时未知数的系数不能直接等于,要+= 3.题意貌似说的有问题,D为- ...

  5. hdu 5755(高斯消元——模线性方程组模板)

    PS. 看了大神的题解,发现确实可以用m个未知数的高斯消元做.因为确定了第一行的情况,之后所有行的情况都可以根据第一行推. 这样复杂度直接变成O(m*m*m) 知道了是高斯消元后,其实只要稍加处理,就 ...

  6. 【高斯消元】BZOJ 1770: [Usaco2009 Nov]lights 燈

    Description 貝希和她的閨密們在她們的牛棚中玩遊戲.但是天不從人願,突然,牛棚的電源跳閘了,所有的燈都被關閉了.貝希是一個很膽小的女生,在伸手不見拇指的無盡的黑暗中,她感到驚恐,痛苦與絕望. ...

  7. 【高斯消元】Poj 1222:EXTENDED LIGHTS OUT

    Description In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each ...

  8. 【高斯消元】BZOJ 1013: [JSOI2008]球形空间产生器sphere

    Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁 ...

  9. ZJUT 1423 地下迷宫(期望DP&高斯消元)

    地下迷宫 Time Limit:1000MS  Memory Limit:32768K Description: 由于山体滑坡,DK被困在了地下蜘蛛王国迷宫.为了抢在DH之前来到TFT,DK必须尽快走 ...

随机推荐

  1. 采用MVC模式创建一个简单的javascript App

    初次翻译,翻译的不好,还请见谅 JavaScript中最好的一部分之一,也可能是最糟糕的. 在HTML文档的头部添加一个开始和结束脚本标记,并在其中引入一些意大利面条式的代码,毫无疑问这是一种过分简单 ...

  2. 2020年11月CKA新题考试心得体会

    1 什么是CKA CKA,即Certificated Kubernetes Administrator,CNCF官方提供的Kubernetes技能认证,含金量还是不错的.还有CKAD,相对简单一些,没 ...

  3. Spring @Transaction 注解是如何执行事务的?

    前言 相信小伙伴一定用过 @Transaction 注解,那 @Transaction 背后的秘密又知道多少呢? Spring 是如何开启事务的?又是如何进行提交事务和关闭事务的呢? 画图猜测 在开始 ...

  4. 进程与线程 .Net Core系列-多线程

    进程与线程 进程: 狭义定义:进程是正在运行的程序的实例 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分 ...

  5. hdu1232 并查集总结

    前言 在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中. 这一类问题其特点是看似并 ...

  6. VRRP简介以及配置案例

    一.背景 二.VRRP 概念介绍 三.实验操作 一.背景 局域网中的用户终端通常采用配置一个默认网关的形式访问外部网络,如果此时默认网关设备发生故障,将中断所有用户终端的网络访问,这很可能会给用户带来 ...

  7. js笔记11

    1.针对表单的 from  input  select  textarea type="radio/checkbox/password/button/tetx/submit/reset/&q ...

  8. Samba常见漏洞利用

    Samba简介 Samba是linux和unix系统上实现smb协议的一个免费软件,由服务器及客户端程序构成,Samba是面向Linux和Unix环境的Windows互操作性套件.它适用于在可能包括L ...

  9. yoyogo v1.7.4 发布,支持 grpc v1.3.8 & etcd 3.5.0

    YoyoGo (Go语言框架)一个简单.轻量.快速.基于依赖注入的微服务框架( web .grpc ),支持Nacos/Consoul/Etcd/Eureka/k8s /Apollo等 . https ...

  10. http连接复用进化论

    HTTP协议是应用层协议,它定义万维网客户端如何与服务器进行通信.它在传输层的TCP协议的基础上进行数据传输 HTTP 1.0 在HTTP 1.0时代,默认一个http请求对应一个TCP连接,没有任何 ...