#include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> #include <cmath> #include <iostream> #include <string> #include <vector> #include <queue> #include <stack> #include <map> #include <list> #include <algorithm> using namespace std; typedef long long LL; typedef double DB; typedef unsigned long long ULL; typedef unsigned int Uint; const int INT_INF=0x3fffffff; const LL LL_INF=0x3fffffffffffffff; const DB EPS=1e-9; const DB PI=3.14159265358979323846; const int N=10010; const int E=10010; #define PB push_back #define MP make_pair #define MH make_heap #define PH push int A[N][N]; int Up[N], Down[N]; //Up 存储的是分子, Down存储的是分母 bool Free[N]; int equation, variable; void debug() { printf("The Matrix is :\n"); for(int i=0; i<=variable+1; i++) { printf("%4d",i); if(i==0) printf("|"); } printf("\n"); for(int i=0; i<=variable+1; i++) { printf("---"); if(i==0) printf("-+"); else printf("-"); } printf("\n"); for(int i=1; i<=equation; i++) { printf("%4d|",i); for(int j=1; j<=variable+1; j++) { printf("%4d",A[i][j]); } printf("\n"); } printf("\n"); } /***************************************************************************/ /* 功能说明: /* 1、不需带入参数,参数已经在 build() 函数中设置好了 /* 2、函数返回 -1 :无解 /* 3、函数返回 0 :有且仅有一组解 /* 4、函数返回 其他正数 :有多解,返回的值是不确定变元的个数 /**************************************************************************/ int gauss() { int col=1, row=1; for(; row<=equation && col<=variable; row++, col++) { int max_row=row; //找到 col 那列元素绝对值最大的那行与当前行交换,减小精度误差 for(int i=row+1; i<=equation; i++) if(abs(A[i][col])>abs(A[max_row][col])) max_row=i; //如果 col 那列元素最大是 0,表明这一列全部是 0,处理下一列 if(A[max_row][col]==0) { row--; continue; } //如果不是同一行,交换元素 if(max_row!=row) { for(int i=col; i<=variable+1; i++) swap(A[max_row][i], A[row][i]); } //枚举要删去的行 //for(int i=row+1; i<=equation; i++) for(int i=1; i<=equation; i++) { if(i==row) continue; if(A[i][col]==0) continue; int GCD=__gcd(abs(A[i][col]), abs(A[row][col])); int ta=abs(A[row][col]) / GCD; int tb=abs(A[i][col]) / GCD; // printf("ta=%d tb=%d\n",ta,tb); //如果异号,应该相加 if((A[i][col]>0 && A[row][col]<0) || (A[i][col]<0 && A[row][col]>0)) tb=-tb; //对于 j 的起点问题,如果我是只把当前行后面的行的元素消掉,我可以是从 col 开始, //但如果是从第一行开始消掉,必须从 1 开始 for(int j=1; j<=variable+1; j++) A[i][j]=A[i][j]*ta-A[row][j]*tb; //A[i][j]-=A[row][j]*tb/ta; } // printf("row=%d col=%d\n", row, col); // debug(); } // debug(); // 1、没有解的情况: for(int i=row; i<=equation; i++) if(A[i][variable+1]!=0) return -1; //表明无解 // 2、无穷解的情况: if(row<variable+1) { for(int i=row-1; i>=1; i--) { int free_x_num=0, free_index=-1; for(int j=1; j<=variable; j++) if(Free[j] && A[i][j]!=0) { free_x_num++; free_index=j; } if(free_x_num>1) continue; Free[free_index]=false; int Up_temp=A[i][variable+1]; int Down_temp=1; for(int j=1; j<=variable; j++) if(A[i][j]!=0 && j!=free_index) { int GCD=__gcd(abs(Down[j]), abs(A[i][j])); int U=Up[j]*A[i][j]/GCD; int D=Down[j]/GCD; GCD=__gcd(abs(D), abs(Down_temp)); int ta=D/GCD; int tb=Down_temp/GCD; Up_temp=Up_temp*ta-U*tb; Down_temp*=ta; GCD=__gcd(abs(Up_temp), abs(Down_temp)); Up_temp/=GCD; Down_temp/=GCD; } if(Up_temp==0) { Up[free_index]=0; continue; } int GCD=__gcd(abs(Up_temp), abs(A[i][free_index])); Down[free_index]=A[i][free_index]/GCD*Down_temp; Up[free_index]=Up_temp/GCD; } return variable-row+1; } // 3、唯一解的情况: for(int i=variable; i>=1; i--) { int Up_temp=A[i][variable+1]; int Down_temp=1; for(int j=i+1; j<=variable; j++) if(A[i][j]!=0) { int GCD=__gcd(abs(Down[j]), abs(A[i][j])); int U=Up[j]*A[i][j]/GCD; int D=Down[j]/GCD; GCD=__gcd(abs(D), abs(Down_temp)); int ta=D/GCD; int tb=Down_temp/GCD; Up_temp=Up_temp*ta-U*tb; Down_temp*=ta; GCD=__gcd(abs(Up_temp), abs(Down_temp)); Up_temp/=GCD; Down_temp/=GCD; } if(Up_temp==0) { Up[i]=0; continue; } int GCD=__gcd(abs(Up_temp), abs(A[i][i])); Down[i]=A[i][i]/GCD*Down_temp; Up[i]=Up_temp/GCD; } return 0; } void build(int n, int m) { memset(Free, true, sizeof(Free)); memset(Up, 0, sizeof(Up)); for(int i=0; i<N; i++) Down[i]=1; variable=n, equation=m; for(int i=1; i<=equation; i++) for(int j=1; j<=variable+1; j++) scanf("%d",&A[i][j]); debug(); } void PRINT(int flag) { if(flag==-1) { printf("NO Solution !\n"); return; } if(flag==0) { for(int i=1; i<=variable; i++) printf("x%d : %d/%d\n", i, Up[i], Down[i]); return; } printf("There are %d variables who are indeterminate !\n",flag); for(int i=1; i<=variable; i++) { printf("x%d : ", i); if(Free[i]) printf("indeterminate !\n"); else printf("%d/%d\n",Up[i], Down[i]); } } int main() { freopen("C:/Users/zhj5chengfeng/Desktop/in.txt","r",stdin); freopen("C:/Users/zhj5chengfeng/Desktop/out.txt","w",stdout); int ca=0; while(~scanf("%d%d", &variable, &equation)) { printf("Case #%d :\n", ++ca); build(variable, equation); PRINT(gauss()); printf("\n\n\n\n"); } return 0; } /* Input: 4 3 1 -2 1 5 3 1 -2 4 -34 0 2 -4 3 -3 5 2 2 1 2 27 2 1 0 3 3 3 -1 5 3 1 -1 2 1 1 -2 -1 2 Output: Case #1 : The Matrix is : 0| 1 2 3 4 5 ----+-------------------- 1| 1 -2 1 5 3 2| 1 -2 4 -34 0 3| 2 -4 3 -3 5 There are 2 variables who are indeterminate ! x1 : indeterminate ! x2 : indeterminate ! x3 : indeterminate ! x4 : indeterminate ! Case #2 : The Matrix is : 0| 1 2 3 ----+------------ 1| 1 2 27 2| 2 1 0 x1 : -9/1 x2 : 18/1 Case #3 : The Matrix is : 0| 1 2 3 4 ----+---------------- 1| 3 -1 5 3 2| 1 -1 2 1 3| 1 -2 -1 2 x1 : 10/7 x2 : 1/-7 x3 : -2/7 */