题解:AcWing 790 数的三次方根
【题目来源】
AcWing:790 数的三次方根 - AcWing题库
【题目描述】
给定一个浮点数,求它的三次方根。
【输入】
共一行,包含一个浮点数。
【输出】
共一行,包含一个浮点数,表示问题的解。
注意,结果保留 位小数。
【输入样例】
1000.00
【输出样例】
10.000000
【核心思想】
-
问题分析:给定一个浮点数 \(x\),需要求它的三次方根,即找到实数 \(y\) 使得 \(y^3 = x\)。由于 \(f(y) = y^3\) 是严格单调递增的连续函数,因此对于任意实数 \(x\),存在唯一的实数解 \(y\),且满足 \(y^3 \geq x\) 的 \(y\) 集合具有单调性,适合二分查找。
-
算法选择:
- 浮点二分:在实数区间 \([-10000, 10000]\) 上进行二分逼近,通过控制精度终止迭代
- 单调性判定:利用 \(y^3\) 的严格单调性,通过比较 \(mid^3\) 与 \(x\) 的大小来缩小搜索区间
-
关键步骤:
- 初始化边界:\(l = -10000\),\(r = 10000\)(覆盖所有可能的三次方根范围)
- 二分迭代:
- 计算中点 \(mid = \frac{l + r}{2}\)
- 若 \(mid^3 \geq x\):\(r = mid\)(解在左半区间)
- 否则:\(l = mid\)(解在右半区间)
- 重复直到 \(r - l \leq 10^{-8}\)
- 输出结果:输出 \(l\)(或 \(r\)),保留 \(6\) 位小数
-
时间/空间复杂度:
- 时间复杂度:\(O(\log \frac{20000}{\epsilon})\),其中 \(\epsilon = 10^{-8}\) 为精度要求,约需 \(50\) 次迭代
- 空间复杂度:\(O(1)\),仅使用常数个浮点变量
-
浮点二分的核心思想:
- 连续函数的零点定理:单调连续函数在区间端点值异号时必存在唯一零点,二分法通过不断缩小区间来逼近该零点
- 精度控制策略:不比较 \(mid^3 = x\)(浮点数精确相等不可靠),而是通过控制区间长度 \(r - l \leq 10^{-8}\) 来保证结果精度。由于输出保留 \(6\) 位小数,区间长度小于 \(10^{-8}\) 可确保四舍五入后的正确性
- 对称区间设计:三次方根可能为负数,因此左右边界设为对称区间 \([-10000, 10000]\),统一处理正负输入
- 无精度损失更新:浮点二分中 \(l = mid\) 和 \(r = mid\) 的更新方式不会导致整数二分的边界问题,因为实数是稠密的,中点始终严格位于区间内部
- 适用于连续单调函数的根求解、实数域上的最优化问题等数值计算场景
【解题思路】

【算法标签】
浮点二分
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int main() {
double x;
cin >> x; // 输入要计算立方根的数值
// 初始化二分查找的左右边界
double l = -10000, r = 10000;
// 当区间长度大于1e-8时继续二分
while (r - l > 1e-8) {
double mid = (l + r) / 2; // 计算中点
// 检查中点的立方是否大于等于x
if (mid * mid * mid >= x)
r = mid; // 如果成立,说明解在左半区间
else
l = mid; // 否则解在右半区间
}
// 输出结果,保留6位小数
printf("%.6lf", l);
return 0;
}
【运行结果】
1000.00
10.000000
浙公网安备 33010602011771号