这段代码展示了两种计算平方根的方法:solve1 使用二分查找计算整数平方根 $\lfloor \sqrt{n} \rfloor$;solve2 使用牛顿迭代法(Newton's Method)在给定初始值的情况下迭代 $k$ 次,以逼近精确的浮点数平方根。
1. 代码逻辑详细分析
solve1()(整数平方根):- 在区间 $[0, n]$ 内进行二分查找。
- 目标是找到最大的整数 $mid$ 使得 $mid^2 \le n$。
- 时间复杂度:$O(\log n)$。
solve2(double x)(牛顿迭代):- 初始值 $x$ 由
solve1()提供(即 $\lfloor \sqrt{n} \rfloor$)。 - 迭代公式:$x_{next} = \frac{1}{2} (x + \frac{n}{x})$。
- 这是牛顿法求 $f(x) = x^2 - n = 0$ 的根,具有平方收敛速度。
- 时间复杂度:$O(k)$。
- 初始值 $x$ 由
main():- 输入 $n$ 和 $k$。
- 输出经过 $k$ 次迭代后的近似值,以及一个布尔值(判断
ans * ans是否完全等于n)。
2. 题目解析
判断题
-
该算法最准确的时间复杂度分析结果为 $O(\log n + k)$。
- 答案:A (正确)
- 分析:
solve1是 $O(\log n)$,solve2的循环执行 $k$ 次。两者是顺序执行关系,总复杂度相加。
-
当输入为 9801 1 时,输出的第一个数为 99。
- 答案:A (正确)
- 分析:$99^2 = 9801$。
solve1(9801)返回 99。solve2(99, 1)计算(99 + 9801/99) / 2 = 99。结果保持不变。
-
对于任意输入的 $n$,随着所输入 $k$ 的增大,输出的第二个数会变成 1。
- 答案:B (错误)
- 分析:只有当 $n$ 是完全平方数时,结果才可能为 1。如果 $n$ 不是完全平方数(如 $n=2$),$\sqrt{n}$ 是无理数,
double类型(有限精度)的平方永远无法精确等于整数 $n$,因此ans * ans == n始终为 0(false)。
-
该程序有存在缺陷。当输入的 $n$ 过大时,第 12 行的乘法有可能溢出,因此应当将 mid 强制转换为 64 位整数再计算。
- 答案:B (错误)
- 分析:题目给定 $n \le 47000$。
solve1中mid的初值约为 $n/2 = 23500$。$23500^2 = 552,250,000$,远小于 32 位有符号整数的最大值(约 $2.14 \times 10^9$)。即使mid接近 46340 才会溢出,而在此程序中mid会迅速向 $\sqrt{n} \approx 216$ 缩小,因此在给定约束下不会溢出。
单选题
-
当输入为 2 1 时,输出的第一个数最接近( )。
- 答案:C (1.5)
- 分析:
solve1(2)返回 $\lfloor \sqrt{2} \rfloor = 1$。solve2(1, 1)执行一次循环:$x = (1 + 2/1) / 2 = 1.5$。
-
当输入为 3 10 时,输出的第一个数最接近( )。
- 答案:B (1.732)
- 分析:$n=3$,$k=10$。牛顿迭代法收敛极快,迭代 10 次后已经极其接近 $\sqrt{3} \approx 1.73205$。
-
当输入为 256 11 时,输出的第一个数( )。
- 答案:A (等于 16)
- 分析:
solve1(256)返回 $16$(因为 $16^2 = 256$)。solve2(16, 11):由于初始值 16 已经是精确根,代入公式 $x = (16 + 256/16)/2 = 16$,无论迭代多少次,结果始终保持 $16.0$。
3. 总结
- 知识点:二分查找、牛顿迭代法、浮点数精度、整数溢出边界。
- 关键理解:牛顿迭代法在初始值选在根附近时收敛极快;浮点数相等判断(
==)在涉及无理数运算时通常不可靠。
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com