CSP-J 2022 入门级 第一轮 阅读程序(3) 第28-34题

本文详细分析了CSP-J2022入门级算法题目的解题思路,涉及二分查找算法求平方根下界和迭代逼近求平方根。题目中,solve1()函数使用二分法寻找满足mid*mid<=n的最大整数mid,solve2()函数通过迭代逐步逼近n的平方根。对于不同输入,文章给出了精确的输出结果和时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目】

CSP-J 2022 入门级 第一轮 阅读程序(3) 第28-34题
阅读程序

01 #include <iostream>
02
03 using namespace std;
04
05 int n, k;
06
07 int solve1()
08 {
09     int l = 0, r = n;
10     while (l <= r) {
11         int mid = (l + r) / 2;
12         if (mid * mid <= n) l = mid + 1;
13         else r = mid - 1;
14     }
15     return l - 1;
16 }
17
18 double solve2(double x)
19 {
20     if (x == 0) return x;
21     for (int i = 0; i < k; i++)
22         x = (x + n / x) / 2;
23     return x;
24 }
25
26 int main()
27 {
28     cin >> n >> k;
29     double ans = solve2(solve1());
30     cout << ans << ' ' << (ans * ans == n) << endl;
31     return 0;
32 }

假设 int 为 32 位有符号整数类型,输入的 n 是不超过 47000 的自然数、 k 是不超过 int 表示范围的自然数,完成下面的判断题和单选题:
判断题
28. 该算法最准确的时间复杂度分析结果为 𝑂(log 𝑛 + 𝑘) 。( )
29. 当输入为“ 9801 1 ”时,输出的第一个数为“ 99 ”。( )
30. 对于任意输入的 n ,随着所输入 k 的增大,输出的第二个数会变成“ 1 ”。( )
31. 该程序有存在缺陷。当输入的 n 过大时,第 12 行的乘法有可能溢出,因此应当将mid 强制转换为 64 位整数再计算。( )
单选题
32. 当输入为“ 2 1 ”时,输出的第一个数最接近( )。
A. 1
B. 1.414
C. 1.5
D. 2
33. 当输入为“ 3 10 ”时,输出的第一个数最接近( )。
A. 1.7
B. 1.732
C. 1.75
D. 2
34. 当输入为“ 256 11 ”时,输出的第一个数( )。
A. 等于 16
B. 接近但小于 16
C. 接近但大于 16
D. 前三种情况都有可能

【题目考点】

1. 二分

【解题思路】

观察solve1函数,明显是二分答案算法。
满足mid*mid<=n时,l=mid+1取右半边。
最后取l-1,由于l都是mid+1,所以最后取到的是满足条件的mid。
可以看出,这个二份答案求的是:满足mid*mid<=n条件的,mid的最大值。
实际就是求⌊n⌋\lfloor \sqrt{n} \rfloorn
至于solve2函数,传入的x是:⌊n⌋\lfloor \sqrt{n} \rfloorn,而当n\sqrt{n}n不是整数时,n/xn/xn/x是个略大于n\sqrt{n}n的数字。⌊n⌋\lfloor \sqrt{n} \rfloorn与n/x二者取平均数后的值赋值给x,x变得更接近n\sqrt{n}n
重复这一过程,会使x不断逼近n\sqrt{n}n

28. 该算法最准确的时间复杂度分析结果为 O(logn+k)O(logn + k)O(logn+k) 。( )
答:正确。solve1函数是二分算法,二分查找的范围为n,复杂度为O(logn)O(logn)O(logn),solve1求出值后,把值传给solve2函数。sovle2函数里面只有k次循环,复杂度为O(k)O(k)O(k),所以整体复杂度为O(logn+k)O(logn+k)O(logn+k)
29. 当输入为“ 9801 1 ”时,输出的第一个数为“ 99 ”。( )
答:正确。
sove1求出⌊n⌋=⌊9801⌋=99\lfloor \sqrt{n}\rfloor=\lfloor \sqrt{9801}\rfloor=99n=9801=99
sove2中x=99,k为1,for循环执行一次,x=(x+n/x)/2=(99+9801/99)/2=99
输出ans为99。
30. 对于任意输入的 n ,随着所输入 k 的增大,输出的第二个数会变成“ 1 ”。( )
答:错误。
随着输入k的增大,ans会接近或等于n\sqrt{n}n,但ans是double类型的,只能保存有限的数位,也就是说只能表示有理数。如果n\sqrt{n}n是无理数,那么ans不可能与n\sqrt{n}n相等,因此ans∗ansans*ansansans也不会等于n,输出的第二个表达式的值会一直为假,输出0。
31. 该程序有存在缺陷。当输入的 n 过大时,第 12 行的乘法有可能溢出,因此应当将 mid 强制转换为 64 位整数再计算。( )
答:错误
题目限定了n最大是47000,第一次求出mid=n/2为23500,midmid为23500223500^2235002=552250000,int类型可以表示该数字,并不会溢出。
而后r=mid-1,下一次mid会变得更小,mid
mid也会更小,因此不会出现溢出的情况。
(如果说n过大会超过题目限定的47000,那极端一点,当n特别大时,转为64位的long long类型计算仍然可能溢出。)
32. 当输入为“ 2 1 ”时,输出的第一个数最接近( )。
A. 1
B. 1.414
C. 1.5
D. 2

答:选C。
solve1传入2,求出结果为⌊2⌋=1\lfloor \sqrt{2} \rfloor = 12=1
把1传入solve2,x为1,循环1次,x = (x+n/x)/2=(1+2/1)/2=1.5,函数的返回值,也就是ans的值为1.5

33. 当输入为“ 3 10 ”时,输出的第一个数最接近( )。
A. 1.7
B. 1.732
C. 1.75
D. 2

答:选B。
solve1传入3,求出结果为⌊3⌋=1\lfloor \sqrt{3} \rfloor = 13=1
把1传入solve2,x为1,循环10次,,每次循环让x=(x+n/x)/2,用模拟运行法

kx
0(1+3/1)/2=2
1(2+3/2)/2=1.75
2(1.75+3/1.75)/2=1.732
3(1.732+3/1.732)/2=1.732

后面不用算了,我们通过分析程序已知x最终会不断接近3\sqrt{3}3的值,进行多次循环后,结果的前几位一定是1.732,不会改变。

34. 当输入为“ 256 11 ”时,输出的第一个数( )。
A. 等于 16
B. 接近但小于 16
C. 接近但大于 16
D. 前三种情况都有可能

答:选A。
solve1的结果为⌊256⌋=16\lfloor \sqrt{256} \rfloor=16256=16,已知256=16\sqrt{256}=16256=16,所以在solve2中x=(x+n/x)/2=(16+256/16)/2=16,每次计算后x的值不变,都是16。因此最后输出的值等于16。

【答案】

  1. 正确
  2. 正确
  3. 错误
  4. 错误
  5. C
  6. B
  7. A
1. CSP-J2022第一: 已知一个正整数数列,求其中连续的子序列,使得它们的和最大。请编写一个程序,计算该最大和。 输入格式: 第一行包含整数n,表示数列的长度。 第二行包含n个整数,表示数列中的元素。 输出格式: 输出一个整数,表示最大和。 例如,输入: 4 -1 2 4 -3 输出: 6 2. CSP-J2022第二: 给定一个n×m的矩阵,矩阵中的元素为0或1。请编写一个程序,计算矩阵中最大的全1子矩阵的面积。 输入格式: 第一行包含两个整数n和m,表示矩阵的行数和列数。 接下来n行,每行m个整数,表示矩阵中对应置的元素。 输出格式: 输出一个整数,表示最大的全1子矩阵的面积。 例如,输入: 4 5 1 0 1 1 1 1 1 1 0 1 1 1 1 1 0 0 1 1 1 1 输出: 6 3. CSP-J2022第三: 给定一个长度为n的数列,求其中最长的下降子序列的长度。下降子序列指的是子序列中任意两个元素的前后顺序变,且前一个元素小于等于后一个元素。 输入格式: 第一行包含整数n,表示数列的长度。 第二行包含n个整数,表示数列中的元素。 输出格式: 输出一个整数,表示最长的下降子序列的长度。 例如,输入: 5 3 1 2 1 3 输出: 3 4. CSP-J2022第四: 给定一个长度为n的数列,求其中最长的上升子序列的长度。上升子序列指的是子序列中任意两个元素的前后顺序变,且前一个元素大于等于后一个元素。 输入格式: 第一行包含整数n,表示数列的长度。 第二行包含n个整数,表示数列中的元素。 输出格式: 输出一个整数,表示最长的上升子序列的长度。 例如,输入: 5 3 1 2 1 3 输出: 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值