CF20B Equation 题解

Content

解方程 \(ax^2+bx+c=0\)

数据范围:\(-10^5\leqslant a,b,c\leqslant 10^5\)

Solution

很明显上求根公式。

先来给大家推推求根公式吧。

\[\begin{aligned}ax^2+bx+c&=0\color{Red}~(a\neq0)\\ax^2+bx&=-c&(1)\\x^2+\dfrac bax&=-\dfrac ca&(2)\\x^2+\dfrac bax+\left(\dfrac{b}{2a}\right)^2&=-\dfrac ca+\left(\dfrac{b}{2a}\right)^2&(3)\\\left(x+\dfrac{b}{2a}\right)^2&=\dfrac{b^2-4ac}{4a^2}&(4)\\x+\dfrac b{2a}&=\pm\sqrt{\dfrac{b^2-4ac}{4a^2}}=\pm\dfrac{\sqrt{b^2-4ac}}{2a}&(5)\\x&=\dfrac{-b\pm\sqrt{b^2-4ac}}{2a}&(6)\end{aligned} \]

(1)将常数项 \(c\) 移到右边。
(2)将方程两边同时除以 \(a\)
(3)配方,由于二次项系数是 \(1\),因此很明显常数项是一次项的一半的平方。为了使方程两边相等,右边也要加上一个常数项。
(4)将等号左边写成 \(a^2\) 的形式,同时将等号右边通分。
(5)开根号,注意右边的结果正负都可以(负负得正)。
(6)将等号左边的常数项移到右边。

这样就得到了求根公式了:

\[\boxed{x_{1,2}=\dfrac{-b\pm\sqrt{b^2-4ac}}{2a}} \]

没错,\(x_1,x_2\) 就表示成原方程的两个解。

然而,看到方程右边的条件了没有?\(a\neq 0\)

而题目中并没有保证 \(a\neq 0\)(事实上有 \(a=0\) 的数据)。

那么就需要分类讨论了:

一、如果 \(a=0\)。分三类。

  1. \(b,c=0\)。那么原方程就变成了 \(0=0\),显然有无数多个解。
  2. \(b=0,c\neq 0\)。那么原方程就变成了 \(c=0\),显然无解。
  3. \(b\neq 0\),那么原方程就变成了 \(bx+c=0\),显然该方程的解只有一个,即 \(-\dfrac cb\)

二、如果 \(a\neq 0\),那么这个方程就是一元二次方程了。依照 \(\Delta\) 分类讨论。

首先得讲讲 \(\Delta\),其实就是上面求根公式中的 \(b^2-4ac\)。为什么要单独拿出这个式子呢?因为这和一元二次方程的解的情况有着密不可分的关系,具体如下:

  • \(\Delta>0\),那么原方程中 \(x_1,x_2\) 显然都不相等因此原方程有两个不同的解。
  • \(\Delta=0\),那么原方程中的 \(x_1,x_2\) 显然都是 \(-\dfrac{b}{2a}\),因此原方程严格上讲有两个相同的解,但原题目貌似将这种情况算为只有一个解了,因此这里默认为有一个解
  • \(\Delta<0\),显然,根号里面如果是负数是不在实数的讨论范围的,因此原方程严格上讲无实数解,但原题目貌似将这种情况算为无解,因此这里默认为无解

其实只要找出 \(\Delta\),这道题目就迎刃而解了,直接那上面三种情况分类讨论即可。注意,在有两个解的时候,本题要求从小到大输出,因此建议先把两个解存储进来(设为 \(x,y\)),然后输出 \(\min\{x,y\}\)\(\max\{x,y\}\)

另外,\(b^2\)\(ac\) 有可能爆出 int 范围内(\(10^5\times 10^5\geqslant2^{31}\)),因此需要开 long long

Code


long long a, b, c;

int main() {
	scanf("%lld%lld%lld", &a, &b, &c);
	long long delta = b * b - 4 * a * c;
	if(!a && !b && !c) return printf("-1"), 0;
    if(!a && !b) return printf("0"), 0;
    if(!a) return printf("1\n%.8lf", -c * 1.0 / b), 0;
	if(delta > 0)
		printf("2\n%.8lf\n%.8lf", min((-b - sqrt(delta)) * 1.0 / (a * 2.0), (-b + sqrt(delta)) * 1.0 / (a * 2.0)), max((-b - sqrt(delta)) * 1.0 / (a * 2.0), (-b + sqrt(delta)) * 1.0 / (a * 2.0)));
	else if(delta == 0)
		printf("1\n%.8lf", -b / (a * 2.0));
	else
		printf("0");
	return 0;
}
posted @ 2021-12-15 22:15  Eason_AC  阅读(48)  评论(0)    收藏  举报