天生我材必有难,千金散尽还债来2小时呕心沥血换来的只要你会解一元二次方程就看得懂

天生我材必有难,千金散尽还债来  •  7天前


#include<bits/stdc++.h>
using namespace std;
int getgcd(int x,int y) {//辗转相除法求系数们的最大公因数
	while(x%y) {
		x=abs(x);
		y=abs(y);
		int t=x%y;
		x=y;
		y=t;
	}
	return y;
}
int main() {
	int t,m,gcd,ta;
	cin>>t>>m;
	while(t--) {
		int a,b,c;
		cin>>a>>b>>c;//系数
		if(a<0) {//为了使得a的系数好算,通乘-1
			a=-a;
			b=-b;
			c=-c;
		}
		int deta=b*b-4*c*a;//计算Δ
		if(deta<0) {//若Δ<0那么无实数解
			cout<<"NO"<<endl;
			continue;
		} else if(deta==0) {//若Δ=0那么有两个相同的实数解现在要处理的只有2a分之负b
			if(b==0) {//当我们的分子负b=0时,整个分式都为0
				cout<<'0'<<endl;
				continue;
			}
			gcd=getgcd(-b,2*a);//当我们的分子负b!=0时,对2a和负b求最大公因数以便约分
			b=-b/gcd;
			a=2*a/gcd;
			cout<<b;
			if(a!=1) {//当a是1时是不用输出的
				cout<<"/"<<a;
			}
			cout<<endl;
			continue;
		}//从此成功进入有两个实数解的部分
		//首先进入化简根式的部分
		vector<pair<int,int>> list;//这个动态数组里<质因数,该质因数的个数>
		for(int i=2; deta>1; i++) {//质因数分解
			if(deta%i==0) {
				int cnt=0;
				while(deta%i==0) {
					deta/=i;
					cnt++;
				}
				list.push_back({i,cnt});
			}
		}
		int w=1,g=1;//w是根号外的,g是根号里的系数
		for(auto p:list) {
			w*=pow(p.first,p.second/2);//众所周知,根号里两个质因数开出变来一个,不用担心0.5,因为int向下取整
			if(p.second%2==1) g*=p.first;//开不出来的放里面
		}
		if(g>1) {//根号里还有东西时,要处理2a分之负b加根号下Δ,不用考虑减法,题目要求输出大的那个实数解
			if(b!=0) {//若分子负b!=0时要处理2a分之负b的部分
				gcd=getgcd(-b,2*a);//对2a和负b求最大公因数以便约分
				b=-b/gcd;
				ta=2*a/gcd;
				if(ta==1) {
					cout<<b<<"+";//当a是1时是不用输出的,+号是为了拼接后面的根号
				} else {
					cout<<b<<"/"<<ta<<"+";//a!=1时将2a分之负b作为最简分数输出,+号是为了拼接后面的根号
				}
			}
			gcd=getgcd(w,2*a);//现在处理2a分之Δ的约分
			w/=gcd;
			ta=2*a/gcd;
			if(w!=1) {
				cout<<w<<"*";//有根号系数的情况
			}
			cout<<"sqrt("<<g<<")";//将开不尽的根号部分输出
			if(ta!=1) {//a!=1时将2a分之Δ作为最简分数输出
				cout<<"/"<<ta;
			}
			cout<<endl;
		} else {//根号被开干净了,对2a和负b加根号开完的结果求最大公因数以便约分
			b=-b+w;//将-b于根号开完的结果合并处理
			gcd=getgcd(b,2*a);
			b/=gcd;
			a=2*a/gcd;
			if(a==1) {//当a是1时是不用输出的,直接输出b
				cout<<b<<endl;
			} else {
				cout<<b<<"/"<<a<<endl;
			}//a!=1时将2a分之b作为最简分数输出
		}
	}
	return 0;
}


评论:

请先登录,才能进行评论