Gauss 消元(模板)

  1 /*
  2     title:Gauss消元整数解/小数解整数矩阵模板
  3     author:lhk
  4     time: 2016.9.11
  5     没学vim的菜鸡自己手打了
  6 */
  7 #include<cstdio>
  8 #include<iostream>
  9 #include<cstring>
 10 #include<algorithm>
 11 #include<cmath>
 12 #define clr(x) memset(x,0,sizeof(x))
 13 #define clrdown(x) memset(x,-1,sizeof(x))
 14 #define maxn 910
 15 #define maxm 910
 16 #define mod 3
 17 using namespace std;
 18 int A[maxn][maxm];//Gauss消元的增广矩阵
 19 int free_x[maxm];//自由变元的位置
 20 int x[maxm];//整数解集
 21 double xd[maxm];//小数解集
 22 void init(int n,int m);//矩阵初始化操作
 23 int gauss(int n,int m);//gauss消元部分
 24 void print(int n);//输出解集
 25 int exgcd(int a,int b,int &x,int &y);//扩展欧几里得求逆元,对于模mod的矩阵除法需要
 26 int lcm(int a,int b);
 27 int gcd(int a,int b);
 28 int main()
 29 {
 30     int T,n,m;
 31     scanf("%d",&T);
 32     while(T--)
 33     {
 34         scanf("%d%d",&n,&m);
 35         init(n,m);
 36         int p=gauss(n,m);
 37         if(p==-1)
 38         {
 39             printf("no answer\n");
 40             return 0;
 41          }
 42         if(p==-2)
 43         {
 44                printf("have float answer\n");
 45             return 0;
 46         }
 47         printf("the num of free_x is %d\n",p);
 48         print(m);
 49     }
 50     return 0;
 51 }
 52 //输出解的和,自由变元数量以及各个解
 53 void print(int n)
 54 {
 55     //    若有小数解换为xd输出
 56     int sum=0;
 57     for(int i=0;i<n;i++)
 58         sum+=x[i];
 59     printf("sum=%d\n",sum);
 60     for(int i=0;i<n;i++)
 61         printf("x%d=%d\n",i+1,x[i]);
 62     return ;
 63 }
 64 //读入增广矩阵
 65 void init(int n,int m)
 66 {
 67     clr(A);
 68     for(int i=0;i<n;i++)
 69         for(int j=0;j<=m;j++)
 70         scanf("%d",&A[i][j]);
 71     clrdown(x);
 72     clr(free_x);
 73     return ;
 74 }
 75 int gauss(int n,int m)//输出-1是无解,-2是有小数解,>=0则是自由变元的数量和全为整数解
 76 {
 77     int k,col,num=0,max_r,dou,max_x,LCM,ta,tb;
 78 //k为当前操作行,col为操作主元素所在列
 79     for(k=0,col=0;k<n && col<m;k++,col++)
 80     {
 81         //若A[K][col]不为col列最大,则将k行与k+1到n-1行中A[i][col]绝对值最大的行交换
 82         max_r=k;
 83         max_x=abs(A[k][col]);
 84         for(int i=k+1;i<n;i++)
 85             if(max_x<abs(A[i][col]))
 86             {
 87                 max_x=abs(A[i][col]);
 88                 max_r=i;
 89             }
 90         if(max_r!=k)
 91         {
 92             for(int j=col;j<=m;j++)
 93                 swap(A[k][j],A[max_r][j]);
 94         }
 95         //若k到n-1行A[i][col]全为0,则主元素指向当前行下一列的元素
 96         if(A[k][col]==0)
 97         {
 98             k--;
 99             free_x[num++]=col;
100             //自由变元为当前col
101             continue;
102         }
103         for(int i=k+1;i<n;i++)
104         if(A[i][col])
105         {
106             LCM=lcm(abs(A[k][col]),abs(A[i][col]));
107             ta=LCM/abs(A[i][col]);
108             tb=LCM/abs(A[k][col]);
109             if(A[k][col]*A[i][col]<0) tb=-tb;//若符号不同则取反
110             for(int j=col;j<=m;j++)
111             {
112                     A[i][j]=A[i][j]*ta-A[k][j]*tb;
113                  // A[i][j]=((A[i][j]*ta-A[k][j]*tb)%mod+mod)%mod; //模mod矩阵的消元
114             }
115         }
116     }
117     //k行及之后若有(0,0,0……,0,a)(a!=0)的行,则无解输出-1
118     for(int i=k;i<n;i++)
119         if(A[i][col]!=0)
120             return -1;
121     int temp;
122     //对自由变元的赋值,可有多种方式
123     //若为小数解则换为xd;
124     for(int i=0;i<num;i++)
125         x[free_x[i]]=0;
126     //int  xi,yi; exgcd需要
127     for(int i=k-1,c=m-1;i>=0;c=m-1,i--)
128     {
129         temp=A[i][m];
130         while(x[c]!=-1)
131         {
132             if(A[i][c])
133                  temp-=x[c]*A[i][c];
134                 //temp=((temp-(x[c]*A[i][c])%mod)%mod+mod)%mod;//模mod矩阵的回代
135             c--;
136         }
137         if(temp%A[i][c]!=0) return -2;
138         x[c]=temp/A[i][c];
139         /*exgcd(A[i][c],mod,xi,yi);
140         xi=(xi%mod+mod)%mod;
141         x[c]=(temp*xi%mod+mod)%mod;*/ //模mod 矩阵的x[i]的赋值
142     }
143     return col-k;
144 }
145 int exgcd(int a,int b,int &x,int &y)
146 {
147     if(b==0)
148     {
149         x=1;
150         y=0;
151         return a;
152     }
153     else
154     {
155         int r=exgcd(b,a%b,y,x);
156         y-=x*(a/b);
157         return r;
158     }
159 }
160 int gcd(int a,int b)
161 {
162     int c;
163     while(b!=0)
164     {
165         c=a%b;
166         a=b;
167         b=c;
168     }
169     return a;
170 }
171 int lcm(int a,int b)
172 {
173     return a/gcd(a,b)*b;
174 }
时间: 2024-10-22 23:30:28

Gauss 消元(模板)的相关文章

高斯消元 模板

照着czyuan的那个模板,手敲了一遍,存一下. 貌似今天一整天就看了一下高斯消元的知识,然后看了模板,又手敲了一遍. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #define LL __int64 8 const int

高斯消元模板(kuangbin大神版本)

#include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> #include<math.h> using namespace std; const int MOD = 7; const int MAXN = 50; int a[MAXN][MAXN];//增广矩阵 int x[MAXN];//解集 bool free_x[MAXN];//标记是否是不确定的

hdu 5755(GAuss 消元)

Gambler Bo Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1152    Accepted Submission(s): 471Special Judge Problem Description Gambler Bo is very proficient in a matrix game. You have a N×M m

HDU 3359 高斯消元模板题,

http://acm.hdu.edu.cn/showproblem.php?pid=3359 题目的意思是,由矩阵A生成矩阵B的方法是: 以a[i][j]为中心的,哈曼顿距离不大于dis的数字的总和 / 个数,就是矩阵B的b[i][j] 现在给出B,要求A 那么我们设A矩阵为a[1][1], a[1][2], a[1][3]..... 那么对于每一个b[i][j]我们有b[i][j] = (a[1][1] + a[1][2] + ... + ) / cnt 所以这样可以建议一条方程,然后guas

求一个n元一次方程的解,Gauss消元

const Matrix=require('./Matrix.js') /*Gauss 消元 传入一个矩阵,传出结果 */ function Gauss(matrix){ let l=[];//是否为自由元 let ans=[];//存储解 const n=matrix.Column-1;//解的个数 const EPS=0.00001; let res=0,r=0; for(let i=0;i<matrix.Column;i++){ for(let j=r;j<matrix.Row;j++)

POJ1830开关问题——gauss消元

题目链接 分析: 第一个高斯消元题目,操作是异或.奇偶能够用0.1来表示,也就表示成bool类型的方程,操作是异或.和加法没有差别 题目中有两个未知量:每一个开关被按下的次数(0.1).每一个开关的转换次数. 题目仅仅和操作次数的奇偶有关,所以用0.1表示之后,对于每一个开关的转换次数就已经知道了.所以仅仅有一个未知量.能够线性表示.练习使用模板 const int maxn = 40; int a[maxn][maxn]; int gauss(int N, int M) { int r, c,

高斯消元模板

高斯消元: 其实就是用矩阵初等变换解线性方程组,只是他要求每次选取的主元一定要是最大值. 模板 #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> using namespace std; const int MAXN=10000; int a[MAXN][MAXN];//增广矩阵 int x[MAXN];//解集 bool free_x[MAXN];/

高斯消元整数消元模板

高斯消元就是来接方程组的.(可以跟矩阵联系在一起) #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; const int MAXN = 1e2+5; int equ, var;///equ个方程 var个变量 int a[MAXN][MAXN];///增广矩阵 int x

gauss消元

题意描述:有n个星球,m台望远镜.每台望远镜有一个开始时间和结束时间,但只给出了月.日的信息,没有给出年份,每台望远镜记录了它所观测的星球上发生的各类事件的次数.每类事件持续的时间是恒定的,且不会超过365天,不管在哪个星球上发生.告诉你每台望远镜的起止时间,和它观测到的各类时间发生的次数.问每类事件持续多长时间?可能有多个解,输出一个可行解即可. 数据范围:n<200,m<200 分析:设第i类时间持续的时间为xi,第i个望远镜的观测时间长度为Ci,它观测到的各类事件发生的次数为fi,则第i