当前位置: 首页 > news >正文

CSP-J系列【2023】P9750 [CSP-J 2023] 一元二次方程题解

题目背景

众所周知,对一元二次方程 ax2+bx+c=0(a=0),可以用以下方式求实数解:

  • 计算 Δ=b2−4ac,则:
    1. 若 Δ<0,则该一元二次方程无实数解。
    2. 否则 Δ≥0,此时该一元二次方程有两个实数解 x1,2​=2a−b±Δ​​。

例如:

  • x2+x+1=0 无实数解,因为 Δ=12−4×1×1=−3<0。
  • x2−2x+1=0 有两相等实数解 x1,2​=1。
  • x2−3x+2=0 有两互异实数解 x1​=1,x2​=2。

在题面描述中 a 和 b 的最大公因数使用 gcd(a,b) 表示。例如 12 和 18 的最大公因数是 6,即 gcd(12,18)=6。

题目描述

现在给定一个一元二次方程的系数 a,b,c,其中 a,b,c 均为整数且 a=0。你需要判断一元二次方程 ax2+bx+c=0 是否有实数解,并按要求的格式输出。

在本题中输出有理数 v 时须遵循以下规则:

  • 由有理数的定义,存在唯一的两个整数 p 和 q,满足 q>0,gcd(p,q)=1 且 v=qp​。

  • 若 q=1,则输出 {p},否则输出 {p}/{q},其中 {n} 代表整数 n 的值;

  • 例如:

    • 当 v=−0.5 时,p 和 q 的值分别为 −1 和 2,则应输出 -1/2
    • 当 v=0 时,p 和 q 的值分别为 0 和 1,则应输出 0

对于方程的求解,分两种情况讨论:

  1. 若 Δ=b2−4ac<0,则表明方程无实数解,此时你应当输出 NO

  2. 否则 Δ≥0,此时方程有两解(可能相等),记其中较大者为 x,则:

    1. 若 x 为有理数,则按有理数的格式输出 x。

    2. 否则根据上文公式,x 可以被唯一表示为 x=q1​+q2​r​ 的形式,其中:

      • q1​,q2​ 为有理数,且 q2​>0;
      • r 为正整数且 r>1,且不存在正整数 d>1 使 d2∣r(即 r 不应是 d2 的倍数);

    此时:

    1. 若 q1​=0,则按有理数的格式输出 q1​,并再输出一个加号 +
    2. 否则跳过这一步输出;

    随后:

    1. 若 q2​=1,则输出 sqrt({r})
    2. 否则若 q2​ 为整数,则输出 {q2}*sqrt({r})
    3. 否则若 q3​=q2​1​ 为整数,则输出 sqrt({r})/{q3}
    4. 否则可以证明存在唯一整数 c,d 满足 c,d>1,gcd(c,d)=1 且 q2​=dc​,此时输出 {c}*sqrt({r})/{d}

    上述表示中 {n} 代表整数 {n} 的值,详见样例。

    如果方程有实数解,则按要求的格式输出两个实数解中的较大者。否则若方程没有实数解,则输出 NO

输入格式

输入的第一行包含两个正整数 T,M,分别表示方程数和系数的绝对值上限。

接下来 T 行,每行包含三个整数 a,b,c。

输出格式

输出 T 行,每行包含一个字符串,表示对应询问的答案,格式如题面所述。

每行输出的字符串中间不应包含任何空格

输入输出样例

输入 #1复制

9 1000
1 -1 0
-1 -1 -1
1 -2 1
1 5 4
4 4 1
1 0 -432
1 -3 1
2 -4 1
1 7 1

输出 #1复制

1
NO
1
-1
-1/2
12*sqrt(3)
3/2+sqrt(5)/2
1+sqrt(2)/2
-7/2+3*sqrt(5)/2

说明/提示

【样例 #2】

见附件中的 uqe/uqe2.in 与 uqe/uqe2.ans

【数据范围】

对于所有数据有:1≤T≤5000,1≤M≤103,∣a∣,∣b∣,∣c∣≤M,a=0。

测试点编号M≤特殊性质 A特殊性质 B特殊性质 C
11
220
3103
4103
5103
6103
7,8103
9,10103

其中:

  • 特殊性质 A:保证 b=0;
  • 特殊性质 B:保证 c=0;
  • 特殊性质 C:如果方程有解,那么方程的两个解都是整数。

题目概述

一元二次方程是初中数学的核心内容,也是CSP-J竞赛中的常见题型。题目要求我们编写程序解标准形式的一元二次方程ax²+bx+c=0,并按照特定格式输出结果。本题考察了对数学公式的理解和编程实现能力。

数学原理回顾

一元二次方程的解由判别式Δ=b²-4ac决定:

  1. 当Δ>0时,方程有两个不同的实数根
  2. 当Δ=0时,方程有一个实数重根
  3. 当Δ<0时,方程无实数解

求根公式为:x = [-b±√(Δ)]/(2a)

解法一:直接计算法

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;void solve(int a, int b, int c) {int delta = b*b - 4*a*c;if(delta < 0) {cout << "NO\n";return;}double sqrt_delta = sqrt(delta);double x1 = (-b + sqrt_delta) / (2.0*a);double x2 = (-b - sqrt_delta) / (2.0*a);if(delta == 0) {cout << fixed << setprecision(2) << x1 << "\n";} else {if(x1 < x2) swap(x1, x2);cout << fixed << setprecision(2) << x2 << " " << x1 << "\n";}
}int main() {int T, a, b, c;cin >> T;while(T--) {cin >> a >> b >> c;solve(a, b, c);}return 0;
}

解法二:优化计算法

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;void solve(int a, int b, int c) {int delta = b*b - 4*a*c;if(delta < 0) {cout << "NO\n";return;}double root = -b/(2.0*a);if(delta == 0) {cout << fixed << setprecision(2) << root << "\n";} else {double offset = sqrt(delta)/(2.0*a);cout << fixed << setprecision(2) << root-offset << " " << root+offset << "\n";}
}int main() {int T, a, b, c;cin >> T;while(T--) {cin >> a >> b >> c;solve(a, b, c);}return 0;
}

优化法先计算中间值减少重复运算,提高精度和效率。

算法分析

  1. 精度处理‌:使用double类型和setprecision保证输出精度
  2. 特殊情况处理‌:当a=0时题目保证不会出现,否则需要额外判断
  3. 时间复杂度‌:两种方法都是O(1)每测试用例,整体O(T)
  4. 空间复杂度‌:O(1),仅使用固定数量的变量

边界情况测试

测试时应考虑以下边界情况:

  1. 判别式刚好为0的情况
  2. 大系数导致计算溢出的情况(题目保证不会)
  3. 根为整数和分数混合的情况
  4. 两个根非常接近的情况

代码优化技巧

  1. 使用中间变量减少重复计算
  2. 提前计算公共部分(-b/2a)
  3. 使用swap保证输出顺序
  4. 使用fixed和setprecision控制输出格式

数学知识扩展

  1. 韦达定理‌:x1+x2=-b/a,x1x2=c/a
  2. 配方法‌:ax²+bx+c=a(x+b/2a)²+(4ac-b²)/4a
  3. 图像性质‌:抛物线顶点坐标为(-b/2a, (4ac-b²)/4a)

常见错误分析

  1. 忘记处理负判别式情况
  2. 输出顺序不符合题目要求
  3. 整数除法导致精度丢失
  4. 没有使用足够精度的数据类型

实际应用

一元二次方程在以下领域有广泛应用:

  1. 物理中的抛体运动计算
  2. 工程中的最优解问题
  3. 经济学中的成本收益分析
  4. 计算机图形学中的曲线交点计算

总结

两种解法各有优势:直接计算法直观易懂,适合初学者理解;优化计算法效率更高,适合对性能有要求的场景。掌握一元二次方程的编程实现不仅能提升算法能力,也能加深对数学原理的理解。

http://www.dtcms.com/a/295075.html

相关文章:

  • SSH 一键互信配置脚本 V2.0 使用指南
  • 卡尔曼滤波数据融合
  • AI 及开发领域动态与资源汇总(2025年7月23日)
  • 【LeetCode】算法详解#9 ---旋转图像
  • QT开发---基础介绍及环境搭建
  • STM32中SystemCoreClockUpdate函数解读
  • 双写缓冲区 Redo Log
  • 基于GitHub的Terraform自动化管理最佳实践
  • 多服务器批量发布软件
  • Linux编程:9、线程编程-互斥锁与条件变量
  • 扫地机产品的电池CQC认证遵循哪个标准?
  • 1. 一份“从 0 到 1” 的 WSL(Windows Subsystem for Linux)速查手册
  • J2EE模式---视图助手模式
  • ospf多区域
  • git的使用,推送仓库github
  • Hierarchical-Localization 安装与常见问题解决手册
  • MSTP多生成树协议
  • 【西北工业大学公开课】导引系统原理(全61讲)周军 -个人笔记版 5000字
  • 基于多种机器学习的水质污染及安全预测分析系统的设计与实现【随机森林、XGBoost、LightGBM、SMOTE、贝叶斯优化】
  • Parasoft为金融服务打造统一测试平台,提升安全、合规与交付效率
  • Shell函数
  • 无人设备遥控器之无线网络技术篇
  • Linux 一文详谈Vim编辑器的使用
  • 面试150 最大子数组和
  • C语言学习(days09)
  • useEffect
  • Java异常处理核心原理与最佳实践
  • 数据驱动未来:构建强大AI系统的基石
  • QPixmap::scaled参数说明
  • 床上肢体康复机器人的机械结构设计cad【7张】三维图+设计说明书