首页 > 代码库 > Gauss 消元(模板)
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 else154 {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 }
Gauss 消元(模板)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。