天生我材必有难,千金散尽还债来 • 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;
}
评论:
请先登录,才能进行评论