CSP历年复赛题-P9750 [CSP-J 2023] 一元二次方程
原题链接:https://www.luogu.com.cn/problem/P9750
题意解读:根据公式,输出结果。
解题思路:本题是一道较为繁琐的模拟题,分情况讨论即可,需要细心。
先计算deta = b * b - 4 * a * c
1、deta < 0则无根,输出NO
2、如果有根,较大的根是:-b/2a+sqrt(deta)/2abs(a)
3、判断deta是否是完全平方数
3.1 deta是完全平方数,说明根是有理数,直接计算x=sqrt(deta),然后分a正负将-b/2a+x/2abs(a)的符号、分子、分母分别计算出来
//较大的根为-b/2a+sqrt(deta)/2abs(a)
int x = sqrt(deta);
if(x * x == deta) //如果根是有理数,也就是deta是完全平方数,直接计算根的分子、分母
{
int s, c, d; //符号,分子,分母
if(a > 0) c = sqrt(deta) - b, d = 2 * a;
if(a < 0) c = sqrt(deta) + b, d = 2 * abs(a);
if(c < 0) s = -1;
else s = 1;
c = abs(c), d = abs(d);
int g = gcd(c, d);
c /= g, d /= g;
if(c == 0) cout << 0; //注意如果根是0,要输出0
if(c != 0)
{
if(s < 0) cout << "-";
cout << c;
if(d > 1) cout << "/" << d;
}
}
3.2 deta不是完全平方数
3.2.1 先计算q1
//q1=-b/2a
if(b != 0) //b=0则不用输出q1
{
int s = -1; //q1的符号
if(a * b < 0) s *= -1; //计算q1的符号
if(s < 0) cout << "-"; //输出符号
int c = abs(b), d = abs(2 * a); //q1的分子分母
int g = gcd(c, d);
c /= g, d /= g;
cout << c;
if(d > 1) cout << "/" << d;
}
3.2.2 再将sqrt(deta)分解为x*sqrt(r),也就是消除deta中的完全平方因子
//sqrt(deta) = x*sqrt(r)
//根的后半部分为x*sqrt(r)/2abs(a)
int x = 1;
for(int i = sqrt(deta); i >= 1; i--)
{
if(deta % (i * i) == 0)
{
x = i; //找到deta里最大的完全平方因子
break;
}
}
int r = deta / (x * x);
3.2.3 最后计算q2
//q2=x/2abs(a)
int c = x, d = 2 * abs(a); //q2的分子,分母
int g = gcd(c, d);
c /= g, d /= g;
if(b != 0) cout << "+";
if(c == 1 && d == 1) cout << "sqrt(" << r << ")";
if(c != 1 && d == 1) cout << c << "*sqrt(" << r << ")";
if(c == 1 && d != 1) cout << "sqrt(" << r << ")/" << d;
if(c != 1 && d != 1) cout << c << "*sqrt(" << r << ")/" << d;
100分代码:
#include <bits/stdc++.h>
using namespace std;
int t, m, a, b, c;
int gcd(int a, int b)
{
if(b == 0) return a;
return gcd(b, a % b);
}
int main()
{
cin >> t >> m;
while(t--)
{
cin >> a >> b >> c;
int deta = b * b - 4 * a * c;
if(deta < 0)
{
cout << "NO" << endl;
continue;
}
//较大的根为-b/2a+sqrt(deta)/2abs(a)
int x = sqrt(deta);
if(x * x == deta) //如果根是有理数,也就是deta是完全平方数,直接计算根的分子、分母
{
int s, c, d; //符号,分子,分母
if(a > 0) c = sqrt(deta) - b, d = 2 * a;
if(a < 0) c = sqrt(deta) + b, d = 2 * abs(a);
if(c < 0) s = -1;
else s = 1;
c = abs(c), d = abs(d);
int g = gcd(c, d);
c /= g, d /= g;
if(c == 0) cout << 0; //注意如果根是0,要输出0
if(c != 0)
{
if(s < 0) cout << "-";
cout << c;
if(d > 1) cout << "/" << d;
}
}
else
{
//q1=-b/2a
if(b != 0) //b=0则不用输出q1
{
int s = -1; //q1的符号
if(a * b < 0) s *= -1; //计算q1的符号
if(s < 0) cout << "-"; //输出符号
int c = abs(b), d = abs(2 * a); //q1的分子分母
int g = gcd(c, d);
c /= g, d /= g;
cout << c;
if(d > 1) cout << "/" << d;
}
//sqrt(deta) = xsqrt(r)
//根的后半部分为xsqrt(r)/2abs(a)
//q2=x/2abs(a)
int x = 1;
for(int i = sqrt(deta); i >= 1; i--)
{
if(deta % (i * i) == 0)
{
x = i; //找到deta里最大的完全平方因子
break;
}
}
int r = deta / (x * x);
int c = x, d = 2 * abs(a); //q2的分子,分母
int g = gcd(c, d);
c /= g, d /= g;
if(b != 0) cout << "+";
if(c == 1 && d == 1) cout << "sqrt(" << r << ")";
if(c != 1 && d == 1) cout << c << "*sqrt(" << r << ")";
if(c == 1 && d != 1) cout << "sqrt(" << r << ")/" << d;
if(c != 1 && d != 1) cout << c << "*sqrt(" << r << ")/" << d;
}
cout << endl;
}
return 0;
}