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

CSP-S 2022 提高级 第一轮 阅读程序(3)

【题目】

CSP-S 2022 提高级 第一轮 阅读程序(3)

1  #include <iostream>
2  #include <algorithm>
3  
4  using namespace std;
5  
6  const int MAXL = 1000;
7  
8  int n, k, ans[MAXL];
9  
10 int main(void) 
11 {
12     cin >> n >> k;
13     if (!n) cout << 0 << endl;
14     else 
15     {
16         int m = 0;
17         while (n) 
18         {
19             ans[m++] = (n % (-k) + k) % k;
20             n = (ans[m - 1] - n) / k;
21         }
22         for (int i = m - 1; i >= 0; i--)
23             cout << char(ans[i] >= 10 ?
24                          ans[i] + 'A' - 10 :
25                          ans[i] + '0');
26         cout << endl;
27     }
28     return 0;
29 }

假设输入的 n 在 int 范围内,k 为不小于 2 且不大于 36 的正整数,完成下面的判断题和单选题:

判断题
1.该算法的时间复杂度为 O ( log ⁡ k n ) O(\log_k n) O(logkn)
2.删除第 23 行的强制类型转换,程序的行为不变。
3.除非输入的 n 为 0,否则程序输出的字符数为 ⌊ log ⁡ k ∣ n ∣ ⌋ + 1 \lfloor \log_k|n|\rfloor+1 logkn+1
单选题
4.当输入为“100 7”时,输出为( )。
A. 202
B. 1515
C. 244
D. 1754

5.当输入为“-255 8”时,输出为( )。
A. 1400
B. 1401
C. 417
D. 400

6.当输入为“1000000 19”时,输出为( )。
A. BG939
B. 87GIB
C. 1CD428
D. 7CF1B

【题目考点】

1. 数学取模

数学取模相关概念
证明:C++中取模运算为 % \% %,一定有 a % b a\%b a%b等于 a % ( − b ) a\%(-b) a%(b)
已知C++中除法运算的商为向0取整,设a除以b的商向0取整后为q。
所以有 a = q ∗ b + r a = q*b+r a=qb+r,其中r为 a % b a\%b a%b
设a除以b的实数商为c,c向零取整为q。
则a除以-b的实数商为-c,-c和c是相反数,相反数向零取整的结果也互为相反数,所以-c向零取整为-q。
根据 a = q ∗ b + r a = q*b+r a=qb+r a = ( − q ) ∗ ( − b ) + r a = (-q)*(-b)+r a=(q)(b)+r
其中-q是a除以-b向零取整的结果,r即为 a % ( − b ) a\%(-b) a%(b)
所以 a % b a\%b a%b等于 a % ( − b ) a\%(-b) a%(b)

【解题思路】

10 int main(void) 
11 {
12     cin >> n >> k;
13     if (!n) cout << 0 << endl;
14     else 
15     {
16         int m = 0;
17         while (n) 
18         {
19             ans[m++] = (n % (-k) + k) % k;
20             n = (ans[m - 1] - n) / k;
21         }
22         for (int i = m - 1; i >= 0; i--)
23             cout << char(ans[i] >= 10 ?
24                          ans[i] + 'A' - 10 :
25                          ans[i] + '0');
26         cout << endl;
27     }
28     return 0;
29 }

输入n和k,n为0时就输出0。
只要n不为0就进行循环。
ans[m++]=(n%(-k)+k) ,结合m初值为0,可以看出这是在做数组填充,填充的数在ans数组中的下标范围是0~m-1。
首先n%(-k)等于n%k(见【题目考点】)。
题目给定k是正整数,而(n%k+k)%k,就是在求数学取模 n   m o d   k n\ mod\ k n mod k的结果(见数学取模相关概念)
所以这一句的意义是:将 n   m o d   k n\ mod\ k n mod k填充到ans数组中。
下一句n=(ans[m-1]-n)/k;,可以转为n=-(n-ans[m-1])/k;
ans[m-1]就是上一次填充到数组中的 n   m o d   k n\ mod\ k n mod k,根据除法定理,一定有商q满足 n = k ∗ q + ( n   m o d   k ) n=k*q+(n\ mod\ k) n=kq+(n mod k),q是 ⌊ n k ⌋ \lfloor \frac{n}{k} \rfloor kn。那么 ( n − ( n   m o d   k ) ) / k (n - (n\ mod\ k))/k (n(n mod k))/k就是q,即 ⌊ n k ⌋ \lfloor \frac{n}{k} \rfloor kn
所以n=(ans[m-1]-n)/k;所做的运算为把n变为 − ⌊ n k ⌋ -\lfloor \frac{n}{k} \rfloor kn
以上过程是将n在k进制下进行数位分离,但是每分离出一位后,该数值的符号取反。将分离出的各个数位填入ans数组中。其中较小下标保存低位数字,较大下标保存高位数字。
而后从高位到低位遍历,输出分离出的各个数字,对于大于等于10的数字,将其转为大写字母输出,其中’A’表示10,'B’表示11,……,'Z’表示35。

【试题答案及解析】

判断题
1.该算法的时间复杂度为 O ( log ⁡ k n ) O(\log_k n) O(logkn)
答:T
m是数值是n在k进制下的位数,其值 m = ⌊ log ⁡ k n ⌋ + 1 m=\lfloor \log_k n\rfloor+1 m=logkn+1。17行的while循环和22行的for循环的循环次数都是m次。总体时间复杂度为 O ( m ) = O ( log ⁡ k n ) O(m)=O(\log_k n) O(m)=O(logkn)
2.删除第 23 行的强制类型转换,程序的行为不变。
答:F
由于ans数组为int类型,int类型和char类型量进行运算的表达式的类型也是int类型。因此ans[i]+'A'-10ans[i]+'0'的值都是int类型。整个三目运算表达式ans[i]>=10 ? ans[i]+'A'-10 : ans[i]+'0'的值的类型也是int类型。
cout输出int类型的值,会输出整数,不会输出字符。强转char类型后,用cout输出可以输出字符。因此去掉强转char类型后,输出会改变。

3.除非输入的 n 为 0,否则程序输出的字符数为 ⌊ log ⁡ k ∣ n ∣ ⌋ + 1 \lfloor \log_k|n|\rfloor+1 logkn+1
答:T
输出m个字符,其中n的符号改变并不会改变m
第20行的操作为 n = ( n − ( n   m o d   k ) ) / k n=(n - (n\ mod\ k))/k n=(n(n mod k))/k,无论n是正数还是负数,操作都会去掉n的最低位,使n的位数减少1。因此该操作执行的次数就是n的位数,根据n在k进制下的位数公式,以及对数运算中真数必须大于0,有 m = ⌊ log ⁡ k ∣ n ∣ ⌋ + 1 m=\lfloor \log_k |n|\rfloor+1 m=logkn+1

单选题
4.当输入为“100 7”时,输出为( )。
A. 202
B. 1515
C. 244
D. 1754

答:A
该问题的计算方法为:每次取 n   m o d   k n\ mod\ k n mod k,而后n变为n除以k的商并将符号取反,将取出的数字从后向前排列,即为结果。
其中mod运算为数学取模,即为求n/k的商向下取整时的余数,保证余数为非负整数。

除法式余数
100/7142
-14/7-20
2/702

5.当输入为“-255 8”时,输出为( )。
A. 1400
B. 1401
C. 417
D. 400

答:B

除法式余数
-255/8-321
32/840
-4/8-14
1/801

结果为1401
6.当输入为“1000000 19”时,输出为( )。
A. BG939
B. 87GIB
C. 1CD428
D. 7CF1B

答:B

除法式余数
1000000/195263111(B)
-52631/19277118(I)
算出最后两位就能确定答案是B。

http://www.kler.cn/a/293267.html

相关文章:

  • 边缘的检测
  • css:盒子模型
  • ubuntu中apt-get的默认安装路径。安装、卸载以及查看的方法总结
  • 相机光学(四十二)——sony的HDR技术
  • 在Java中使用ModelMapper简化Shapefile属性转JavaBean实战
  • 前端常用布局模板39套,纯CSS实现布局
  • Redis进阶(五):集群
  • AWS-亚马逊网络服务(基础服务)-AWS 定价计算器-概述与动手部署:
  • c++ 实现线程池
  • 关于pip和conda环境路径不同的解决办法。
  • Mysql递归查询
  • 蜜罐网络MHN安装过程中的坑
  • Webpack 的loader和plugin原理
  • 类比推理-错题集
  • SpringBoot开发——如何防御XSS攻击
  • sqli-labs靶场(56-60)
  • 云计算之ECS
  • 常工院星闪节能团队参加悉尼大学设计交流项目
  • 中间代码例题
  • OSPF 协议介绍
  • Zipkin链路追踪②:如何集成?
  • 网络训练和推理过程
  • Android切换日夜模式导致Activity重建
  • C/C++的自由落体运动
  • 服务器数据恢复—磁盘坏扇区导致raid6阵列崩溃的数据恢复案例
  • 校园体育装备展-2025中国(深圳)国际学校体育装备展览会