题目描述
已知n元线性一次方程组。
其中:n<=50, 系数是[b][color=red]整数<=100(有负数),bi的值都是整数且<300(有负数)(特别感谢U14968 mmqqdd提出题目描述的说明)(redbag:是mqd自己要我写的= =)[/color][/b].
编程任务:
根据输入的数据,编程输出方程组的解的情况。
输入输出格式
输入格式:第一行:未知数的个数。以下n行n+1列:分别表示每一格方程的系数及方程右边的值。
输出格式:如果方程组无实数解输出-1;
如果有无穷多实数解,输出0;
如果有唯一解,则输出解(小数点后保留两位小数)。
输入输出样例
输入样例#1:
复制
3 2 -1 1 1 4 1 -1 5 1 1 1 0
输出样例#1: 复制
x1=1.00 x2=0 x3=-1.00
这个高斯消元的板子略恶心。
我发现我写了一辈子的错的高斯消元,现在感觉很是不好233.
#include <iostream> #include <cstdio> #include <queue> #include <cmath> using namespace std; #define reg register inline int read() { int res = 0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } int n; double a[55][55]; double ans[55]; inline void Gauss() { for (reg int i = 1 ; i <= n ; i ++) { int piv = i; for (reg int j = i + 1 ; j <= n ; j ++) if (fabs(a[piv][i]) < fabs(a[j][i])) piv = j; if (piv != i) for (reg int j = 1 ; j <= n + 1 ; j ++) swap(a[piv][j], a[i][j]); if (fabs(a[i][i]) < 1e-8) continue; double div = a[i][i]; for (reg int j = 1 ; j <= n + 1 ; j ++) a[i][j] /= div; for (reg int j = 1 ; j <= n ; j ++) if (i != j) { div = a[j][i]; for (reg int k = 1 ; k <= n + 1 ; k ++) a[j][k] -= div * a[i][k]; } } } int main() { n = read(); for (reg int i = 1 ; i <= n ; i ++) for (reg int j = 1 ; j <= n + 1 ; j ++) scanf("%lf", &a[i][j]); Gauss(); bool opt1 = 0; bool opt2 = 0; for(int i = 1 ; i <=n ; i ++){ int j = 1; while (fabs(a[i][j]) < 1e-8 and j <= n + 1) j++; if(j > n + 1) opt1 = 1; else if(j == n + 1) opt2 = 1; } if(opt2) { printf("-1"); return 0; } if(opt1) { printf("0"); return 0; } for (reg int i = n ; i >= 1 ; i --) { ans[i] = a[i][n+1]; for (reg int j = i - 1 ; j >= 1 ; j --) { a[j][n+1] -= ans[i] * a[j][i]; a[j][i] = 0; } } for (reg int i = 1 ; i <= n ; i ++) if (fabs(ans[i]) < 1e-8) printf("x%d=0 ", i); else printf("x%d=%.2lf ", i, ans[i]); return 0; }