P9750题解
场上唯一没挂的题,竟然还是大模拟,代码八九十行,接下来慢慢讲。
题目传送门
题目大意
求解形如 NO,有实数解输出较大的那个,但需要按照一定格式输出,也就是
这样讲有点绕,具体可以看原题描述。
其中
显然,若
解题思路
既然是模拟,按照题意模拟即可,麻烦在输出。
注意坑点:很多人以为取较大的解就是取
具体思路在这里讲太麻烦,看代码吧,但有点长。
完整代码(赛时)
#include <bits/stdc++.h>
using namespace std;
int t,m,a,b,c,delta;
void you(int delta)//处理有理数输出
{
int p=-b+sqrt(delta),w=-b-sqrt(delta);//计算两个解的分子
int q=2*a;//计算分母
if (p*1.0/q<w*1.0/q) p=w;//取较大解
if (p%q==0 && w%q==0)//如果整除直接输出p/q
{
cout<<p/q;
return;
}
if ((p<0 && q>0) || (p>0 && q<0)) cout<<'-';//如果为负输出负号
p=abs(p);
q=abs(q);//取绝对值
int k=__gcd(p,q);//求最大公因数
p/=k;
q/=k;//约分
if (q==1) cout<<p;//如果分母为1直接输出分子
else if (p==0) cout<<0;//如果分子为0直接输出0
else printf("%d/%d",p,q);//否则输出p/q的形式
}
int f(int delta)//化简根号,如果根号下的数的因子中有完全平方数,则可以将其分离出来
{
int ans=1;
for (int i=2;i*i<=delta;i++)
while(delta%(i*i)==0)
{
ans*=i;
delta/=i*i;
}
return ans;
}
void wu(int delta)//处理无理数输出
{
if (-b*1.0/(2*a))//如果q1不等于0
{
you(0);//按有理数输出q1
cout<<'+';//记得输出一个加号
}
int k=f(delta);//计算根号化简后的系数
delta/=k*k;//根号下的数要除以k^2
double q2=fabs(1.0*k/(2*a));//计算q2
if (q2==1) printf("sqrt(%d)",delta);//如果等于1直接省略
else if (q2==floor(q2)) printf("%.0f*sqrt(%d)",q2,delta);//如果是整数直接保留小数点0位输出
else if (1/q2==floor(1/q2) && 1/q2!=0) printf("sqrt(%d)/%.0f",delta,1/q2);//如果1/q2是整数,那么将q2作为分母输出,具体见题意
else//否则按照有理数输出q2
{
int c=k;
int d=2*a;
int x=__gcd(c,d);
c/=x;
d/=x;
if ((c<0 && d>0) || (c>0 && d<0))
{
c=abs(c);
d=abs(d);
}
if (c!=1) cout<<abs(c)<<'*';//注意输出乘号,与平常数学中不同
printf("sqrt(%d)/%d",delta,d);
}
cout<<endl;
}
int main()
{
//freopen("uqe.in","r",stdin);
//freopen("uqe.out","w",stdout);
cin>>t>>m;
while(t--)
{
cin>>a>>b>>c;
delta=b*b-4*a*c;//计算delta
if (delta<0) cout<<"NO"<<endl;//如果小于0说明没有实数解
else
{
if (sqrt(delta)==floor(sqrt(delta)))//由于保证delta是整数,如果根号下delta是整数,按照有理数输出
{
you(delta);
cout<<endl;
}
else wu(delta);//否则按照无理数输出
}
}
return 0;//完结撒花
}