高斯消元矩阵

文章目录


一、前言


二、算法

模板:

c++ 复制代码
/*
*功能: 列选主元消元法
*@Author: lzyws739307453
*@Language: C++
*@File Name: Gauss.cpp
*@Create Time: 2019年05月05日 星期日
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5;
//输出矩阵
void printM(double a[][MAXN], int n) {
   for (int i = 1; i <= n; i++) {
       for (int j = 1; j <= n + 1; j++)
           printf("%10f,", a[i][j]);
       printf("\n");
   }
}
//选择列主元并进行消元
void SelectColE(double a[][MAXN], int n) {
   double temp; //用于记录消元时的因数
   for (int i = 1; i <= n; i++) {
       int r = i;
       for (int j = i + 1; j <= n; j++)
           if (fabs(a[j][i]) > fabs(a[r][i]))
               r = j;
       if (r != i)
           for (int j = i; j <= n + 1; j++)
               swap(a[i][j], a[r][j]);//与最大主元所在行交换
       for (int j = i + 1; j <= n; j++) {//消元
           temp = a[j][i] / a[i][i];
           for (int k = i; k <= n + 1; k++)
               a[j][k] -= a[i][k] * temp;
       }
       printf("第%d列消元后:\n", i);
       printM(a, n);
   }
}
//高斯消元法(列选主元)
void Gauss(double a[][MAXN], int n) {
   SelectColE(a, n);//列选主元并消元成上三角
   printf("上三角的结果:\n");
   printM(a, n);
   for (int i = n; i >= 1; i--) {//回代求解
       for (int j = i + 1; j <= n; j++)
           a[i][n + 1] -= a[i][j] * a[j][n + 1];
       a[i][n + 1] /= a[i][i];
   }
}
//测试函数
int main() {
   double a[5][MAXN] = {
           {0,   0,   0,   0,   0},
           {0,   2,   1,  -1,   8},
           {0,  -3,  -1,   2, -11},
           {0,  -2,   1,   2,  -3}
   };
   Gauss(a, 3);
   //3个方程3个未知数
   for (int i = 1; i <= 3; i++)
       printf("X%d = %9f\n", i, a[i][4]);
   return 0;
}

1.Matrix Equation


题解:

bitset优化版本见收藏夹,感觉那个才算是正解

代码:

c 复制代码
#include<bits/stdc++.h>

using namespace std;
#define int long long
const int mod = 998244353;
const int N = 210;
int a[N][N];//增广矩阵
int x[N];//解集
bool freeX[N];//标记是否为自由变元
int n;
int A[N][N],B[N][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!=0
  for(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 qpow(int base,int power) {
  int res = 1;
  while(power) {
      if(power & 1) res = res*base%mod;
      base = base*base%mod;
      power >>= 1;
  }return res;
}

signed main(){
  int equ,var;//equ个方程,var个变元

  cin >> n;
  equ = n; var = n;

  for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) cin >> A[i][j];
  }

  for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) cin >> B[i][j];
  }

  int ans = 1;

  for (int k = 0; k < n; k++) {
      //对于c的第几列
      memset(a,0,sizeof(a));
      for (int i = 0; i < n; i++) {
          for (int j = 0; j < n; j++) {
              a[i][j] = A[i][j];
          }
          a[i][n] = 0;
          if(A[i][i] == B[i][k]) a[i][i] = 0;
          else a[i][i] = 1;
      }
      int freeNum=Gauss(equ,var);//自由元个数
      ans = ans*qpow(2,freeNum);
      ans %= mod;
  }

  cout  << ans << endl;

//        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);
//                else
//                    printf("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]);
//        }
}

三、总结

相关推荐
Unlyrical20 小时前
splice, io_uring_prep_splice 调用(无效参数)
linux·服务器·c++·unix
weixin_3077791321 小时前
软件演示环境动态扩展与成本优化:基于目标跟踪与计划扩展的AWS Auto Scaling策略
算法·云原生·云计算·aws
Carl_奕然21 小时前
【机器视觉】一文掌握常见图像增强算法。
人工智能·opencv·算法·计算机视觉
放羊郎21 小时前
人工智能算法优化YOLO的目标检测能力
人工智能·算法·yolo·视觉slam·建图
Lucis__21 小时前
STL设计模式探秘:容器适配器&仿函数
c++·容器·stl·仿函数
无敌最俊朗@1 天前
友元的作用与边界
算法
无敌最俊朗@1 天前
C++ 对象布局之padding(填充字节)
开发语言·c++
Miraitowa_cheems1 天前
LeetCode算法日记 - Day 104: 通配符匹配
linux·数据结构·算法·leetcode·深度优先·动态规划
小龙报1 天前
《DevC++支持C++11等与其软件分辨率低的解决办法》
c语言·c++·windows·蓝桥杯·pat考试·学习方法·dvc++
程序员东岸1 天前
从零开始学二叉树(上):树的初识 —— 从文件系统到树的基本概念
数据结构·经验分享·笔记·学习·算法