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. Redis系列(一):安装

    本系列介绍Redis,从安装到使用,太简单的使用不介绍了,介绍一些比较有意思的功能,也会介绍一些原理性的东西.本篇先介绍Redis的单实例安装.Redis还可以做到高可用,通过哨兵和集群可以做到高可用 ...

  2. oracle数据库归档日志量陡增分析

    ============= oracle数据库archivelog暴增分析 ==================== 前言 归档量突然增长到981G/天,导致归档目录使用率告警 归档日志量异常暴增会导 ...

  3. 《Docker基础与实战,看这一篇就够了》

    什么是Docker? Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术 ...

  4. 不下软件,照样可以完美正确格式化树莓派SD卡!(恢复U盘/SD卡到满容量)

    树莓派作用千千万,系统崩溃的理由也数不胜数(不要问我为啥知道),所以系统的重装和sd卡的格式化也在所难免.顺便给大家看一下我今天的成果,我不就是不小心摔了一下我的树莓派...我和sd卡一定是冤家! 捡 ...

  5. 使用axios模拟表单提交

    1.需求背景 最近在实验室写一个Spring前后端分离的项目,项目中使用Spring Security组件实现系统的认证和授权,当Security的认证模式设置为FormLogin时(如下代码),前端 ...

  6. Java-Java8特性(更新中)

    Java8新特性 之前零零散散写了很多java8的内容,今天做一个整理,也算是整理用到的内容,当然细化的话还有很多,只是说暂时用不到,为了面试的话已经够了 日期计算 Lambda表达式 函数式接口(比 ...

  7. 解决mac中adb: command not found

    在Mac系统中,很多时候第一次在Android SDK中使用adb的时候.无法使用.会提示-bash: abd: command not found. 造成此类现象的原因是:未配置Android的环境 ...

  8. 怎么停掉或关闭运行的npm run dev

    可以直接Ctrl+C就会出现 输入是就可以了

  9. Linux 中使用 QT Charts 显示温度传感器

    前一篇笔记中实现了QT的Label控件显示CPU的温度,只能显示当前的温度,并不能反映CPU温度的变化情况,现在来实现使用QT Charts的曲线图实现一个实时曲线来显示CPU的温度. 添加对Qt C ...

  10. 渗透测试工具Burpsuite操作教程

    Burpsuite简介 Burp Suite 是一款专业的Web和移动应用程序渗透测试工具,是用于攻击web 应用程序的集成平台,包含了许多工具.Burp Suite为这些工具设计了许多接口,以加快攻 ...