P9750 [CSP-J2023] 一元二次方程 题解

· · 题解

CSP-J2023_T3 题目链接

前置知识

  1. 一元二次方程 ax ^ 2 + bx + c = 0 (a \neq 0),求根公式为:

    x_{1,2}=\dfrac{-b\pm\sqrt{b^2-4ac}}{2a}
  2. \sqrt{a^2b}=a\sqrt{b}(a,b\ge0)

题面简述

对一元二次方程 ax ^ 2 + bx + c = 0 (a \neq 0),可以用以下方式求实数解:

共给 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 种情况讨论了:

  1. \sqrt{\Delta} 为有理数 sq 时:此时 \Delta 时完全平方数。x=\color{Orange}\dfrac{-b+sq}{2a}。只需将分子 -b+sq 与分母 2a 约分后输出即可。

  2. \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; } ```