Guass消元

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

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

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

洛谷P3389

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cctype>
  6. #include<cmath>
  7. using namespace std;
  8. inline int read(){
  9. int x=0,w=0;char c=getchar();
  10. while(!isdigit(c))w|=c=='-',c=getchar();
  11. while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
  12. return w?-x:x;
  13. }
  14. namespace star
  15. {
  16. const int maxn=105;
  17. double a[maxn][maxn];
  18. int n;
  19. inline void work(){
  20. n=read();
  21. for(int i=1;i<=n;i++)
  22. for(int j=1;j<=n+1;j++)a[i][j]=(double)read();
  23. for(int i=1;i<=n;i++){
  24. int mx=i;
  25. for(int j=i+1;j<=n;j++)
  26. if(fabs(a[j][i])>fabs(a[mx][i]))mx=j;
  27. swap(a[i],a[mx]);
  28. if(!a[i][i])return (void)puts("No Solution");
  29. for(int j=1;j<=n;j++){
  30. if(j==i)continue;
  31. double tmp=a[j][i]/a[i][i];
  32. for(int k=i+1;k<=n+1;k++)
  33. a[j][k]-=a[i][k]*tmp;
  34. }
  35. }
  36. for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]/a[i][i]);
  37. }
  38. }
  39. signed main(){
  40. star::work();
  41. return 0;
  42. }

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

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
\]

解线性方程组即可。

题目给定有解。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cctype>
  6. #include<cmath>
  7. using namespace std;
  8. const int maxn=12;
  9. double b[maxn][maxn],a[maxn][maxn];
  10. int n;
  11. int main(){
  12. scanf("%d",&n);
  13. for(int i=1;i<=n+1;i++)
  14. for(int j=1;j<=n;j++)scanf("%lf",&b[i][j]);
  15. for(int i=1;i<=n;i++)
  16. for(int j=1;j<=n;j++)
  17. a[i][j]=(b[i][j]-b[i+1][j])*2;
  18. for(int i=1;i<=n;i++){
  19. for(int j=1;j<=n;j++)
  20. a[i][n+1]+=b[i][j]*b[i][j]-b[i+1][j]*b[i+1][j];
  21. }
  22. for(int i=1;i<=n;i++){
  23. int mx=i;
  24. for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[mx][i]))mx=j;
  25. swap(a[mx],a[i]);
  26. for(int j=1;j<=n;j++){
  27. if(j==i)continue;
  28. double tmp=a[j][i]/a[i][i];
  29. for(int k=i+1;k<=n+1;k++)
  30. a[j][k]-=a[i][k]*tmp;
  31. }
  32. }
  33. for(int i=1;i<=n;i++)printf("%.3lf ",a[i][n+1]/a[i][i]);
  34. return 0;
  35. }

求行列式的值

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

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

求逆矩阵

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

  1. 给原矩阵右边接一个等大的单位矩阵。
  2. 高斯消元,将原矩阵转为单位矩阵。
  3. 右侧矩阵即为所求。
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cctype>
  6. #include<cmath>
  7. #define int long long
  8. using namespace std;
  9. inline int read(){
  10. int x=0,w=0;char c=getchar();
  11. while(!isdigit(c))w|=c=='-',c=getchar();
  12. while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
  13. return w?-x:x;
  14. }
  15. namespace star
  16. {
  17. const int maxn=405,mod=1e9+7;
  18. int n,a[maxn][maxn<<1];
  19. inline int fpow(int a,int b){
  20. int ans=1;
  21. for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;
  22. return ans;
  23. }
  24. inline void work(){
  25. n=read();
  26. for(int i=1;i<=n;i++){
  27. for(int j=1;j<=n;j++)a[i][j]=read();
  28. a[i][n+i]=1;
  29. }
  30. for(int i=1;i<=n;i++){
  31. int mx=i;
  32. for(int j=i+1;j<=n;j++)
  33. if(a[mx][i]<a[j][i])mx=j;
  34. swap(a[mx],a[i]);
  35. if(!a[i][i])return (void)puts("No Solution");
  36. int inv=fpow(a[i][i],mod-2);
  37. for(int j=1;j<=n;j++){
  38. if(j==i)continue;
  39. for(int tmp=a[j][i]*inv%mod,k=1;k<=n*2;k++)//k可以从i+1开始,不会更新下三角
  40. a[j][k]=(a[j][k]-a[i][k]*tmp%mod+mod)%mod;
  41. }
  42. }
  43. for(int i=1;i<=n;i++){
  44. for(int tmp=fpow(a[i][i],mod-2),j=1;j<=n;j++)
  45. printf("%lld ",a[i][j+n]*tmp%mod);
  46. puts("");
  47. }
  48. }
  49. }
  50. signed main(){
  51. star::work();
  52. return 0;
  53. }

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. 02:database 配置(可能出现严格模式配置问题)

    DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day42', 'USER': 'root', 'P ...

  2. 一文带你.Net混合锁和lock语句

    本文主要讲解.Net基于Monitor.Enter和lock实现互斥锁 Monitor.Enter实现 相比前面的锁来说,混合锁的性能更高,任何引用类型的对象都可以做为锁对象,不需要事先创建指定类型的 ...

  3. mybatis-generator的使用心得

    之前开发了一个亚健康测评系统,使用的是SSM框架,里面第一次使用到了mybatis-generator逆向代码生成工具,很方便,省去了基本的增删改查的mapper文件及sql的编写,还能避免错误,这里 ...

  4. R-常见错误

    错误一:选择了未定义的列(Undefined columns are selected) 改正方法:把目标列转换成因子类型(as.factor) 使用代码如下: 或者: 错误二:太多(36119)的重 ...

  5. 12、如何删除windows服务

    12.1.步骤一: 同时按住"windows"徽标键和"r"键,在弹出的"运行"框中输入"services.msc", ...

  6. Gym 100008E Harmonious Matrices 高斯消元

    POJ 1222 高斯消元更稳 看这个就懂了 #include <bits/stdc++.h> using namespace std; const int maxn = 2000; in ...

  7. 资源:Kafka消息队列下载路径

    Kafka下载路径 http://kafka.apache.org/downloads.html

  8. python opencv处理图片

    1.图像读入:cv2.imread() 使用函数cv2.imread(filepath,flags) 读入图像.第二个参数是要告诉函数应该如何读取这幅图片. cv2.IMREAD_COLOR:默认参数 ...

  9. 大数据-Hadoop虚拟机的准备以及配置(三台机子)

    虚拟机的准备 修改静态IP(克隆的虚拟机) vim /etc/udev/rules.d/70-persistent-net.rules 配置网络: Vim /etc/sysconfig/network ...

  10. python自定义异常,使用raise引发异常

    1.自定义异常类,自定义的异常类必须是Exception或者Error的子类! 1 #!/usr/bin/env python 2 # encoding: utf-8 3 4 class Illega ...