洛谷 P2455 [SDOI2006]线性方程组(高斯消元)

该博客介绍了如何使用高斯消元法解决n元线性一次方程组。题目规定n<=50,系数和bi的值均为整数,且有负数。编程任务是根据输入数据输出方程组的解。当方程组无解时输出-1,有无穷解时输出0,唯一解时输出解的值。博客提供了具体的输入输出格式,并附带了一段通过测试的AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题目描述

已知n元线性一次方程组。

在这里插入图片描述

其中:n<=50, 系数是整数<=100(有负数),bi的值都是整数且<300(有负数)(特别感谢U14968 mmqqdd提出题目描述的说明)(redbag:是mqd自己要我写的= =).

编程任务:

根据输入的数据,编程输出方程组的解的情况。

输入格式

第一行:未知数的个数。以下n行n+1列:分别表示每一格方程的系数及方程右边的值。

在这里插入图片描述

输出格式

如果方程组无实数解输出-1;

如果有无穷多实数解,输出0;

如果有唯一解,则输出解(小数点后保留两位小数)。

输入

3
2 -1 1 1
4 1 -1 5
1 1 1 0

输出

x1=1.00
x2=0
x3=-1.00

首先这道题已经把方程列出来了,算是单纯的板子题了。具体的就不多说了,知识有一些需要注意的已经放在了代码的注释里面。

AC代码如下:
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
typedef int ii;
#define int long long
using namespace std;
const int MOD = 7;
const int MAXN = 110;
double a[MAXN][MAXN];//增广矩阵
double x[MAXN];//解集
bool free_x[MAXN];//标记是否是不确定的变元
int p;
inline int gcd(int a,int b) {
	return b?gcd(b,a%b):a;
}
inline int lcm(int a,int b) {
	return a/gcd(a,b)*b;
}
int Gauss(int equ,int var) {  //qeu代表方程数,val代表变元个数 
	ii i,j,k;
	int max_r,ta,tb,free_x_num, free_index, LCM;
	int col;//当前处理的列
	double temp;
	for(int i = 0; i <= var; i++) {
		x[i] = 0;
		free_x[i] = true;
	}
	col = 0;
	for(k = 0; k<equ && col<var; k++,col++) {
		max_r = k;
		for(i = k+1; i < equ; i++) {
			if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i;
		}
		if(max_r!=k) { //与第k行交换
			for(j = k; j < var+1; j++) swap(a[k][j],a[max_r][j]);
		}
		if(a[k][col]==0) {  //最大的还是为0,即下面的全为0,直接跳到下一行 
			k--;
			continue;
		}
		for(i = k+1; i < equ; i++) {   //经证实,这里会爆long long的,所以不能用整数的找最小公倍数了,所以只能开浮点型矩阵
			if(a[i][col]!=0) {
				double t=a[i][col]/a[k][col];
//				LCM = lcm(abs(a[i][col]),abs(a[k][col]));
//				ta = LCM/fabs(a[i][col]);
//				tb = LCM/fabs(a[k][col]);
//				if(a[i][col]*a[k][col] < 0) tb = -tb;//异号的情况是相加
				for(j = col; j < var+1; j++) {
//					a[i][j] = (a[i][j]*ta-a[k][j]*tb);
					a[i][j]-=t*a[k][j];   //避免爆long long,注释掉的做法是整形的,但是会爆long long
				}
			}
		}
	}
	for(i = k; i < equ; i++) {         //无解 
		if(a[i][col]!=0) return -1;
	}
	if(k < var) {       
		return (var-k);//自由变元个数 
	}
	for(i = var-1; i>=0; i--) {       //计算唯一解 
		temp = a[i][var];
		for(j = i+1; j<var; j++) {
			if(a[i][j]!=0) temp -= a[i][j]*x[j];
		}
		x[i] = 1.0*temp/a[i][i];
	}
	return 0;
}
signed main() {
	int i,j;
	int T;
	cin>>T;
	for(ii i=0;i<T;i++){
		for(ii j=0;j<T+1;j++){
			cin>>a[i][j];
		}	
	}
	int ans=Gauss(T,T);
	if(ans==-1)puts("-1"); //无解
	else if(ans>0)puts("0");  //这里的ans返回的是变元的个数,属于无穷解的情况,但是题目里面说了要输出0
	else
		for(ii i=0;i<T;i++)	
			if(x[i]==0) printf("x%d=0\n",i+1); //为了防止出现-0的情况
			else printf("x%d=%.2lf\n",i+1,x[i]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值