P9750 [CSP-J2023] 一元二次方程 题解
sz_wsy
·
·
题解
CSP-J2023_T3 题目链接
前置知识
-
一元二次方程 ax ^ 2 + bx + c = 0 (a \neq 0),求根公式为:
x_{1,2}=\dfrac{-b\pm\sqrt{b^2-4ac}}{2a}
-
\sqrt{a^2b}=a\sqrt{b}(a,b\ge0)
题面简述
对一元二次方程 ax ^ 2 + bx + c = 0 (a \neq 0),可以用以下方式求实数解:
- 计算 \Delta = b ^ 2 - 4ac,则:
- 若 \Delta < 0,则该方程无实数解。
- 否则 \Delta \geq 0,此时该方程有两个实数解 x_{1, 2} = \dfrac{-b \pm \sqrt \Delta}{2a}。
共给 T 组数据 a,b,c,求该方程的较大实数解。
思路分析
CCF 又考大模拟。 这道题题面描述比较长,我们可以结合样例进行理解。不难发现,难点不在于计算过程,而在于输出时的数据处理:化简、约分等。
分 2 种情况讨论:
-
-
话说回来,题目要求较大解,现在 \dfrac{-b\pm\sqrt{\Delta}}{2a} 中分母 2a 已是正数,\sqrt{\Delta}\geq0,则较大解必为 \color{Red}x=\dfrac{-b {+}\sqrt{\Delta}}{2a}。
接下来又要分 2 种情况讨论了:
-
当 \sqrt{\Delta} 为有理数 sq 时:此时 \Delta 时完全平方数。x=\color{Orange}\dfrac{-b+sq}{2a}。只需将分子 -b+sq 与分母 2a 约分后输出即可。
-
当 \sqrt{\Delta} 为无理数时:此时 \Delta 不是完全平方数。
设 \Delta=k^2t,则 \sqrt{\Delta}=k\sqrt{t}(k 取最大值)。
现在,可将原题输出部分分为 2 部分考虑:
需将此两分数分别约分再输出。即将 $b$ 和 $2a$,$k$ 和 $2a$ 分别约分。**输出时需注意**:若 $b\neq0$,则输出 $-\dfrac{b}{2a}$,此时需要输出 `+`;若 $b=0$,则不用输出 `+`,直接输出 $\dfrac{k\sqrt{t}}{2a}$。
由此,我们可以现写出 $3$ 个函数:
```cpp
//求最大公因数
int gcd(int n,int m){
if(n%m==0) return m;
else return gcd(m,n%m);
}
//约分
void YueFen(){
bool f=(fenzi<0?1:0); //在对负数取模时会出 BUG
if(f) fenzi*=-1;
int k=gcd(fenzi,fenmu);
fenzi/=k;fenmu/=k;
if(f) fenzi*=-1;
}
//将 n 化为 k^2*t(k 最大)的形式
int k,t;
void solve(int n){
for(int i=sqrt(n);i>=1;i--){
int w=n/i/i;
if(w*i*i==n){
k=i;
t=w; //n=k^2*t
return;
}
}
}
```
最后是输出的问题,详细解释见代码:
## 代码呈现
```cpp
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
inline int read(){
int x=0,y=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') y=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch&15),ch=getchar();
return x*y;
}
int T,M,fenzi,fenmu;
int gcd(int n,int m){
if(n%m==0) return m;
else return gcd(m,n%m);
}
void YueFen(){
bool f=(fenzi<0?1:0);
if(f) fenzi*=-1;
int k=gcd(fenzi,fenmu);
fenzi/=k;fenmu/=k;
if(f) fenzi*=-1;
}
int k,t;
void solve(int n){
for(int i=sqrt(n);i>=1;i--){
int w=n/i/i;
if(w*i*i==n){
k=i;
t=w; //n=k^2*t
return;
}
}
}
int main(){
// freopen("uqe.in","r",stdin);
// freopen("uqe.out","w",stdout);
T=read(),M=read();
for(int i=1;i<=T;i++){
int a=read(),b=read(),c=read();
int delta=b*b-4*a*c;
if(delta<0){
printf("NO\n");
continue;
}
if(a<0) a=-a,b=-b,c=-c;
int sq=sqrt(delta);
if(sq*sq==delta){ //有理数
fenzi=-b+sq;
fenmu=2*a;
YueFen();
if(fenmu==1){
printf("%d\n",fenzi);
}else printf("%d/%d\n",fenzi,fenmu);
}else{ //无理数
solve(delta); //sqrt(delta)=k*sqrt(t)
fenzi=-b;
fenmu=a*2;
YueFen();
if(b!=0){
if(fenmu==1){
printf("%d",fenzi);
}else printf("%d/%d",fenzi,fenmu);
printf("+");
}
fenzi=k;
fenmu=a*2;
YueFen();
if(fenzi==1&&fenmu==1){
printf("sqrt(%d)",t);
}else if(fenzi==1){
printf("sqrt(%d)/%d",t,fenmu);
}else if(fenmu==1){
printf("%d*sqrt(%d)",fenzi,t);
}else printf("%d*sqrt(%d)/%d",fenzi,t,fenmu);
printf("\n");
}
}
return 0;
}
```