高斯消元


文章目录

  • 一、线性方程组的求解
  • 二、线性方程组整数类型
  • 三、线性方程组浮点数类型
  • 四、求解模线性方程组
  • 五、求解异或线性方程组
  • 六、Matrix Equation

注:文章内容摘选自其他博客
模板代码来自: 作者:Alex_McAvoy 文章链接:线性代数——高斯消元法

一、线性方程组的求解

在求解线性方程组往往将其系数矩阵(或增广矩阵)化为上三角矩阵。
在化为上三角矩阵后,若增广矩阵中出现形如 0 0 0 0 a 的行,则该线性方程组无解;若增广矩阵中每一行均有非0元素(即上三角矩阵完整)则有唯一解;若含有多个全零行,则说明矩阵中含有自由元,计算矩阵的秩r,自由元的个数就为 n-r。

求解线性方程组(化为上三角矩阵)的步骤:(高斯消元法)
1.消元
2.回代
3.判断解的个数(无解、1个、无穷个)

二、线性方程组整数类型

int a[N][N];//增广矩阵
int x[N];//解集
bool freeX[N];//标记是否为自由变元
int GCD(int a,int b){return !b?a:GCD(b,a%b);
}
int LCM(int a,int b){return a/GCD(a,b)*b;
}
int Gauss(int equ,int var){//返回自由变元个数/*初始化*/for(int i=0;i<=var;i++){x[i]=0;freeX[i]=true;}/*转换为阶梯阵*/int col=0;//当前处理的列int row;//当前处理的行for(row=0;row<equ&&col<var;row++,col++){//枚举当前处理的行int maxRow=row;//当前列绝对值最大的行for(int i=row+1;i<equ;i++){//寻找当前列绝对值最大的行if(abs(a[i][col])>abs(a[maxRow][col]))maxRow=i;}if(maxRow!=row){//与第row行交换for(int j=row;j<var+1;j++)swap(a[row][j],a[maxRow][j]);}if(a[row][col]==0){//col列第row行以下全是0,处理当前行的下一列row--;continue;}for(int i=row+1;i<equ;i++){//枚举要删去的行if(a[i][col]!=0){int lcm=LCM(abs(a[i][col]),abs(a[row][col]));int ta=lcm/abs(a[i][col]);int tb=lcm/abs(a[row][col]);if(a[i][col]*a[row][col]<0)//异号情况相加tb=-tb;for(int j=col;j<var+1;j++) {a[i][j]=a[i][j]*ta-a[row][j]*tb;}}}}/*求解*///无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0for(int i=row;i<equ;i++)if (a[i][col]!=0)return -1;//无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行int temp=var-row;//自由变元有var-row个if(row<var)//返回自由变元数return temp;//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){//计算解集int temp=a[i][var];for(int j=i+1;j<var;j++){if(a[i][j]!=0)temp-=a[i][j]*x[j];}if(temp%a[i][i]!=0)//有浮点数解,无整数解return -2;x[i]=temp/a[i][i];}return 0;
}int main(){int equ,var;//equ个方程,var个变元while(scanf("%d%d",&equ,&var)!=EOF) {memset(a,0,sizeof(a));for(int i=0;i<equ;i++)//输入增广矩阵for(int j=0;j<var+1;j++)scanf("%d",&a[i][j]);int freeNum=Gauss(equ,var);//自由元个数if(freeNum==-1)//无解printf("无解\n");else if(freeNum==-2)//有浮点数解无整数解printf("无整数解\n");else if(freeNum>0){//有无穷多解printf("有无穷多解,自由变元个数为%d\n",freeNum);for(int i=0;i<var;i++){if(freeX[i])printf("x%d是自由变元\n",i+1);elseprintf("x%d=%d\n",i+1,x[i]);}}else{//有唯一解for(int i=0;i<var;i++)printf("x%d=%d\n",i+1,x[i]);}printf("\n");}return 0;
}

三、线性方程组浮点数类型

double a[N][N];//增广矩阵
double x[N];//解集
bool freeX[N];//标记是否为自由变元int Gauss(int equ,int var){//返回自由变元个数/*初始化*/for(int i=0;i<=var;i++){x[i]=0;freeX[i]=true;}/*转换为阶梯阵*/int col=0;//当前处理的列int row;//当前处理的行for(row=0;row<equ&&col<var;row++,col++){//枚举当前处理的行int maxRow=row;//当前列绝对值最大的行for(int i=row+1;i<equ;i++){//寻找当前列绝对值最大的行if(abs(a[i][col])>abs(a[maxRow][col]))maxRow=i;}if(maxRow!=row){//与第row行交换for(int j=row;j<var+1;j++)swap(a[row][j],a[maxRow][j]);}if(fabs(a[row][col])<1e6){//col列第row行以下全是0,处理当前行的下一列row--;continue;}for(int i=row+1;i<equ;i++){//枚举要删去的行if(fabs(a[i][col])>1e6){double temp=a[i][col]/a[row][col];for(int j=col;j<var+1;j++) a[i][j]-=a[row][j]*temp;a[i][col]=0;}}}/*求解*///无解for(int i=row;i<equ;i++)if(fabs(a[i][col])>1e6)return -1;//无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行int temp=var-row;//自由变元有var-row个if(row<var)//返回自由变元数return temp;//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){//计算解集double temp=a[i][var];for(int j=i+1;j<var;j++)temp-=a[i][j]*x[j];x[i]=temp/a[i][i];}return 0;
}

四、求解模线性方程组

问题:什么是模线性方程组?
举个例子:(可能不成立,胡编的)
x%3 = 2
x%5 = 1
x%2 = 1
就是一组线性方程组,在求解时,利用函数的思想,借助扩展欧几里得求解
ps:图片来自:模线性方程组

int a[N][N];//增广矩阵
int x[N];//解集
bool freeX[N];//标记是否为自由变元
int GCD(int a,int b){return !b?a:GCD(b,a%b);
}
int LCM(int a,int b){return a/GCD(a,b)*b;
}
int Gauss(int equ,int var){//返回自由变元个数/*初始化*/for(int i=0;i<=var;i++){x[i]=0;freeX[i]=true;}/*转换为阶梯阵*/int col=0;//当前处理的列int row;//当前处理的行for(row=0;row<equ&&col<var;row++,col++){//枚举当前处理的行int maxRow=row;//当前列绝对值最大的行for(int i=row+1;i<equ;i++){//寻找当前列绝对值最大的行if(abs(a[i][col])>abs(a[maxRow][col]))maxRow=i;}if(maxRow!=row){//与第row行交换for(int j=row;j<var+1;j++)swap(a[row][j],a[maxRow][j]);}if(a[row][col]==0){//col列第row行以下全是0,处理当前行的下一列row--;continue;}for(int i=row+1;i<equ;i++){//枚举要删去的行if(a[i][col]!=0){int lcm=LCM(abs(a[i][col]),abs(a[row][col]));int ta=lcm/abs(a[i][col]);int tb=lcm/abs(a[row][col]);if(a[i][col]*a[row][col]<0)//异号情况相加tb=-tb;for(int j=col;j<var+1;j++) {a[i][j]=((a[i][j]*ta-a[row][j]*tb)%MOD+MOD)%MOD;}}}}/*求解*///无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0for(int i=row;i<equ;i++)if (a[i][col]!=0)return -1;//无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行int temp=var-row;//自由变元有var-row个if(row<var)//返回自由变元数return temp;//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){//计算解集int temp=a[i][var];for(int j=i+1;j<var;j++){if(a[i][j]!=0)temp-=a[i][j]*x[j];temp=(temp%MOD+MOD)%MOD;//取模}while(temp%a[i][i]!=0)//外层每次循环都是求a[i][i],它是每个方程中唯一一个未知的变量temp+=MOD;//a[i][i]必须为整数,加上周期MODx[i]=(temp/a[i][i])%MOD;//取模}return 0;
}

五、求解异或线性方程组

和线性加减方程组类似,只不过在化简上三角行列式的时候变为异或化简。

int a[N][N];//增广矩阵
int x[N];//解集
int freeX[N];//自由变元
int Gauss(int equ,int var){//返回自由变元个数/*初始化*/for(int i=0;i<=var;i++){x[i]=0;freeX[i]=0;}/*转换为阶梯阵*/int col=0;//当前处理的列int num=0;//自由变元的序号int row;//当前处理的行for(row=0;row<equ&&col<var;row++,col++){//枚举当前处理的行int maxRow=row;//当前列绝对值最大的行for(int i=row+1;i<equ;i++){//寻找当前列绝对值最大的行if(abs(a[i][col])>abs(a[maxRow][col]))maxRow=i;}if(maxRow!=row){//与第row行交换for(int j=row;j<var+1;j++)swap(a[row][j],a[maxRow][j]);}if(a[row][col]==0){//col列第row行以下全是0,处理当前行的下一列freeX[num++]=col;//记录自由变元row--;continue;}for(int i=row+1;i<equ;i++){if(a[i][col]!=0){for(int j=col;j<var+1;j++){//对于下面出现该列中有1的行,需要把1消掉a[i][j]^=a[row][j];}}}}/*求解*///无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0for(int i=row;i<equ;i++)if(a[i][col]!=0)return -1;//无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行int temp=var-row;//自由变元有var-row个if(row<var)//返回自由变元数return temp;//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){//计算解集x[i]=a[i][var];for(int j=i+1;j<var;j++)x[i]^=(a[i][j]&&x[j]);}return 0;
}
int enumFreeX(int freeNum,int var){//枚举自由元,统计有解情况下1最少的个数int sta=(1<<(freeNum));//自由元的状态总数int res=INF;for(int i=0;i<sta;++i){//枚举状态int cnt=0;for(int j=0;j<freeNum;j++){//枚举自由元if(i&(1<<j)){cnt++;x[freeX[j]]=1;}elsex[freeX[j]]=0;}for(int k=var-freeNum-1;k>=0;k--){//没有自由元的最下面一行int index=0;for(index=k;k<var;index++){//在当前行找到第一个非0自由元if(a[k][index])break;}x[index]=a[k][var];for(int j=index+1;j<var;++j){//向后依次计算出结果if(a[k][j])x[index]^=x[j];}cnt+=x[index];//若结果为1,则进行统计}res=min(res,cnt);}return res;
}
int main(){memset(a,0,sizeof(a));int equ,var;scanf("%d%d",&equ,&var);for(int i=0;i<equ;i++){//构造初始状态}for(int i=0;i<equ;i++)//最终状态scanf("%d",&a[i][var]);int freeNum=Gauss(equ,var);//获取自由元if(freeNum==-1)//无解printf("inf\n");else if(freeNum==0){//唯一解int res=0;for(int i=0;i<var;i++)res+=x[i];printf("%d\n",res);}else{//多个解int res=enumFreeX(freeNum,var);printf("%d\n",res);}return 0;
}

六、Matrix Equation

2020济南站ICPC真题A题

通过观察发现C矩阵列无关性.通过高斯消元统计每列的自由元的个数即可.
ps(也可以发现答案的解都为2的次幂)

#include<bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 2e2 + 7;
const int mod = 998244353;int a[maxn][maxn];//增广矩阵
int x[maxn];//解集
int freeX[maxn];//自由变元
int n;
int A[maxn][maxn],B[maxn][maxn];
ll poww(ll a,ll b){ll ans=1;while(b > 0){if(b & 1) ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;
}
int Gauss(int equ,int var){for(int i=0;i<=var;i++){x[i]=0;freeX[i]=0;}int col=0;//当前处理的列int num=0;//自由变元的序号int row;//当前处理的行for(row=0;row<equ&&col<var;row++,col++){//枚举当前处理的行int maxRow=row;//当前列绝对值最大的行for(int i=row+1;i<equ;i++){//寻找当前列绝对值最大的行if(abs(a[i][col])>abs(a[maxRow][col]))maxRow=i;}if(maxRow!=row){//与第row行交换for(int j=row;j<var+1;j++)swap(a[row][j],a[maxRow][j]);}if(a[row][col]==0){//col列第row行以下全是0,处理当前行的下一列freeX[num++]=col;//记录自由变元row--;continue;}for(int i=row+1;i<equ;i++){if(a[i][col]!=0){for(int j=col;j<var+1;j++){//对于下面出现该列中有1的行,需要把1消掉a[i][j]^=a[row][j];}}}}for(int i=row;i<equ;i++)if(a[i][col]!=0)return -1;int temp=var-row;//自由变元有var-row个if(row<var)//返回自由变元数return temp;return 0;
}int main(){scanf("%d",&n);for(int i = 0; i < n; i ++){for(int j = 0; j < n; j ++){scanf("%d",&A[i][j]);}}for(int i = 0; i < n; i ++){for(int j = 0; j < n; j ++){scanf("%d",&B[i][j]);}}ll ans = 1;for(int r = 0;r < n; r ++){for(int i = 0;i < n;i++) {for(int j = 0;j < n;j++) {a[i][j] = A[i][j];}}for(int i = 0; i < n; i ++){a[i][i] = (A[i][i] - B[i][r] + 2) % 2;
//             a[i][i] = (A[i][i] * B[i][r]);}int freeNum=Gauss(n,n);if(freeNum == -1) continue;ans = (ans  *  poww(2 , freeNum)) % mod;}printf ("%lld\n",ans);return 0;
}

高斯消元求解四种方程组相关推荐

  1. [学习笔记]高斯消元求解两种特殊问题(带状矩阵/主元法)

    本文章是[学习笔记]概率与期望进阶的一部分 由于时间问题我写的比较简略,所以我把大佬的总结链接贴上来了(应该没什么吧qwq). 1 概述 最常见的当然是随机游走问题了- • fu=∑pu,v∗(fv+ ...

  2. poj2947(高斯消元解同模方程组)

    题目链接:http://poj.org/problem?id=2947 题意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下: p start end a1, a2......ap (1< ...

  3. 矩阵树 Matrix-Tree 定理实现模板(高斯消元求解行列式)

    大佬1博客:https://www.cnblogs.com/zj75211/p/8039443.html 大佬2博客:https://www.cnblogs.com/yangsongyi/p/1069 ...

  4. 【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)

    1.线性方程组 2.高斯消元法 步骤1:通过一系列的加减消元,得到类似 kx=b 的式子,求得最后一个未知量的结果 步骤2:然后逐一回代求解整个 x 向量 以下列方程为例: 第一次加减消元,用第1式子 ...

  5. jzoj3823 遇见 [高斯消元解异或方程组]

    Description Zyh独自一人在街上漫步.Zyh相信不久后应该就可以和她一起漫步,可是去哪里寻找那个她呢?Zyh相信每个人都有一个爱情的号码牌,这个号码牌是一个n*n的矩阵. 每个人都要在矩阵 ...

  6. 高斯消元解同余方程组

    SETI 题意:输入一个素数p和一个字符串s(只包含小写字母和'*'),字符串中每个字符对应一个数字,'*'对应0,'a'对应1,'b'对应2··· eg:str[] = "abc" ...

  7. 解线性方程组——高斯消元の板子

    ATP记得它在很久以前看过一点点高斯消元的东西然后做过一点点题目..但是当时实在是太zz了所以本来就没有很懂这个东西现在更是忘得差不多了.. 所以现在就当重新学一遍了QwQ 一点口胡的解释 高斯消元. ...

  8. POJ 1222 EXTENDED LIGHTS OUT(高斯消元)

    [题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...

  9. BZOJ:4820: [Sdoi2017]硬币游戏BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)

    1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...

  10. bzoj 3143: [Hnoi2013]游走(高斯消元)

    3143: [Hnoi2013]游走 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3171  Solved: 1390 [Submit][Stat ...

最新文章

  1. 【转载】IntelliJ远程调试教程
  2. 线程退出【Linux学习】pthread_create主线程与创建的新线程之间退出关系
  3. cidaemon.exe是什么进程及如何关闭cidaemon.exe进程
  4. php+中午截取,PHP_php字符串截取中文截取2,单字节截取模式,//中文截取2,单字节截取模式 - phpStudy...
  5. Cygwin,Nutch安装配置,检验是否正确(对网友守望者博客的修改---在此感谢守望者)2
  6. 解决deepin微信无法登录
  7. iOS:UIView的block函数实现转场动画---双视图
  8. 动画专业艺术里最懂计算机的,美国数字媒体艺术专业了解一下!
  9. 作业要求 20180925-1 每周例行报告
  10. react-native gradle
  11. 2019 蓝桥杯省赛 B 组模拟赛(一) J. 程序设计:蒜厂年会 环形连续子序列求和问题
  12. python第七章_Python第七章
  13. 图神经网络GNN论文2019-2020顶会列表
  14. win10升级2004失败?
  15. 阿里云的WEB应用防火墙(WAF)能抵挡什么攻击
  16. python编码口诀_【每日一练】python输出 9*9 乘法口诀表
  17. 创建自己免费的论坛、博客网站
  18. 自然语言c,自然语言处理_自然语言处理常用方法举例说明 - 人工智能 - 电子发烧友网...
  19. 绝地求生服务器在线人数,《绝地求生:大逃杀》同时在线人数突破165万 官方就服务器问题向玩家致歉...
  20. linux中设置gvim高亮光标所在行和所在列

热门文章

  1. msxml 6.0 dll 导入问题
  2. c语言读取sgy格式文件,用C语言读写SGY格式的地震数据文件
  3. 限制input输入框的输入字符个数,区别中英文字符
  4. 朱生豪先生的情书 ---- 醒来觉得甚是爱你
  5. java开发小公司跳槽华为od笔试面试过程
  6. 笔记本计算机bios设置,小技巧:关于笔记本BIOS设置的三招
  7. 计算机组成原理笔记 (1):计算机组成概述
  8. 黑马程序员—选择黑马,是我前进的方向
  9. 深蓝-视觉slam-第三节习题
  10. ppt太大怎么压缩整个文件