题解:AcWing 790 数的三次方根

【题目来源】

AcWing:790 数的三次方根 - AcWing题库

【题目描述】

给定一个浮点数,求它的三次方根。

【输入】

共一行,包含一个浮点数。

【输出】

共一行,包含一个浮点数,表示问题的解。

注意,结果保留 位小数。

【输入样例】

1000.00

【输出样例】

10.000000

【核心思想】

  1. 问题分析:给定一个浮点数 \(x\),需要求它的三次方根,即找到实数 \(y\) 使得 \(y^3 = x\)。由于 \(f(y) = y^3\) 是严格单调递增的连续函数,因此对于任意实数 \(x\),存在唯一的实数解 \(y\),且满足 \(y^3 \geq x\)\(y\) 集合具有单调性,适合二分查找。

  2. 算法选择

    • 浮点二分:在实数区间 \([-10000, 10000]\) 上进行二分逼近,通过控制精度终止迭代
    • 单调性判定:利用 \(y^3\) 的严格单调性,通过比较 \(mid^3\)\(x\) 的大小来缩小搜索区间
  3. 关键步骤

    • 初始化边界\(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\) 位小数
  4. 时间/空间复杂度

    • 时间复杂度:\(O(\log \frac{20000}{\epsilon})\),其中 \(\epsilon = 10^{-8}\) 为精度要求,约需 \(50\) 次迭代
    • 空间复杂度:\(O(1)\),仅使用常数个浮点变量
  5. 浮点二分的核心思想

    • 连续函数的零点定理:单调连续函数在区间端点值异号时必存在唯一零点,二分法通过不断缩小区间来逼近该零点
    • 精度控制策略:不比较 \(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
posted @ 2026-07-02 22:47  团爸讲算法  阅读(4)  评论(0)    收藏  举报