Files

11 KiB
Raw Permalink Blame History

NOI CSP-J 初赛专项模拟题:程序基本语句

阅读程序 (程序输入不超过数组或字符串定义的范围,判断题正确填√,错误填×)

(1)

01 #include <iostream>
02 using namespace std;
03 
04 int main() {
05     int x, y;
06     cin >> x >> y;
07     int ans = 1;
08     for (int i = 1; i <= y; i++) {
09         ans = ans * x;
10         ans = ans % 10;
11     }
12     cout << ans << endl;
13     return 0;
14 }

假设输入的 x, y 均为不超过 100 的正整数,完成下面的判断题和单选题:

判断题

  1. 该程序的功能是计算 的值。( )
  2. 程序的输出结果一定是一个小于 10 的整数。( )
  3. 当输入为“2 3”时,输出为“8”。( )

单选题 4. 当输入为“12 2”时,输出为( )。 A. 2 B. 4 C. 24 D. 144 5. 当输入为“2 10”时,输出为( )。 A. 2 B. 4 C. 6 D. 8


(2)

01 #include <iostream>
02 using namespace std;
03 
04 int main() {
05     int n;
06     cin >> n;
07     int a[105];
08     for(int i = 1; i <= n; i++) {
09         cin >> a[i];
10     }
11     int count = 0;
12     for(int i = 1; i <= n; i++) {
13         if(a[i] > 0 && a[i] % 2 == 0) {
14             count = count + a[i];
15         }
16     }
17     cout << count << endl;
18     return 0;
19 }

假设输入的 n 为不超过 100 的正整数,数组元素均为 int 范围内整数,完成下面的判断题和单选题:

判断题 6. 该程序统计的是数组中所有偶数的个数。( ) 7. 如果数组中所有的数都是负数,输出结果为 0。( ) 8. 第 13 行的 a[i] > 0 条件如果去掉,程序的输出结果对于任何输入都不会改变。( )

单选题 9. 当输入 n=5,数组元素为 1 2 3 4 5 时,输出为( )。 A. 2 B. 3 C. 6 D. 9 10. 当输入 n=5,数组元素为 -2 -4 2 4 6 时,输出为( )。 A. 12 B. 6 C. 0 D. -6


(3)

01 #include <iostream>
02 #include <string>
03 using namespace std;
04 
05 int main() {
06     string s;
07     cin >> s;
08     int len = s.length();
09     for (int i = 0; i < len; i++) {
10         if (s[i] >= 'a' && s[i] <= 'z') {
11             s[i] = s[i] - 32;
12         } else if (s[i] >= 'A' && s[i] <= 'Z') {
13             s[i] = s[i] + 32;
14         }
15     }
16     cout << s << endl;
17     return 0;
18 }

假设输入仅包含英文字母,完成下面的判断题和单选题:

判断题 11. 程序执行后,字符串 s 的长度可能会发生改变。( ) 12. 输入 "CSP" 时,输出 "csp"。( ) 13. 该程序实现了大小写字母互换的功能。( )

单选题 14. 当输入 "Hello" 时,输出为( )。 A. hello B. HELLO C. hELLO D. Hello 15. 已知 'a' 的 ASCII 码是 97,'A' 的 ASCII 码是 65,则第 11 行可以改为 s[i] = s[i] - 'a' + 'A',效果不变。该说法( )。 A. 正确 B. 错误 C. 编译错误 D. 运行时错误

(4)

01 #include <iostream>
02 using namespace std;
03 
04 int f(int n) {
05     if (n <= 1) return 1;
06     if (n % 2 == 0)
07         return f(n / 2) + n;
08     else
09         return f(n - 1) + 1;
10 }
11 
12 int main() {
13     int x;
14     cin >> x;
15     cout << f(x) << endl;
16     return 0;
17 }

假设输入的 x 为不超过 1000 的正整数,完成下面的判断题和单选题:

判断题

  1. 当输入 x 为偶数时,函数 f(x) 只会进行递归调用,不会增加数值。( )
  2. 该函数一定会终止,不会出现死循环。( )
  3. 当输入 5 时,输出结果为 6。( )

单选题 4. 当输入 8 时,输出为( )。 A. 13 B. 14 C. 15 D. 16 5. 当输入 10 时,函数 f 被调用的次数(包括 main 中的第一次调用)是( )。 A. 4 B. 5 C. 6 D. 7

(5)

01 #include <iostream>
02 using namespace std;
03 
04 int main() {
05     int n, m;
06     cin >> n >> m;
07     int a[20][20];
08     for (int i = 0; i < n; i++) {
09         for (int j = 0; j < m; j++) {
10             if (i == 0 || j == 0)
11                 a[i][j] = 1;
12             else
13                 a[i][j] = a[i - 1][j] + a[i][j - 1];
14         }
15     }
16     cout << a[n - 1][m - 1] << endl;
17     return 0;
18 }

假设输入的 n, m 均为不超过 15 的正整数,完成下面的判断题和单选题:

判断题

  1. 该程序计算的是组合数学中杨辉三角或类似路径计数的问题。( )
  2. 如果输入 n=1, m=5,输出结果为 5。( )
  3. 无论输入什么正整数,数组 a 中的值都会随 i 和 j 的增大而单调递增(不考虑边界)。( )

单选题 4. 当输入 3 3 时,输出为( )。 A. 4 B. 5 C. 6 D. 10 5. 该程序模拟的计算过程等价于求解从网格左上角 (0,0) 走到右下角 (n-1, m-1) 的路径数,且每次只能向右或向下走。如果输入 4 3,输出结果为( )。 A. 6 B. 10 C. 15 D. 20


三、完善程序 (单选题)

(1) 判断回文数

读入一个正整数 n,判断它是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都一样的整数,例如 121 是回文数,而 123 不是。

01 #include <iostream>
02 using namespace std;
03 
04 int main() {
05     int n, t, y = 0;
06     cin >> n;
07     t = ①;
08     while (t > 0) {
09         y = y * 10 + ②;
10         t = ③;
11     }
12     if (④)
13         cout << "Yes" << endl;
14     else
15         cout << "No" << endl;
16     return 0;
17 }

  1. ①处应填( ) A. 0 B. 1 C. n D. -1
  2. ②处应填( ) A. t / 10 B. t % 10 C. n % 10 D. n / 10
  3. ③处应填( ) A. t / 10 B. t % 10 C. t - 1 D. t + 1
  4. ④处应填( ) A. n == t B. n == 0 C. n == y D. y == t
  5. 如果输入的 n 是 100,循环结束后 y 的值是( ) A. 1 B. 0 C. 001 D. 10

(2) 最大公约数与最小公倍数

输入两个正整数 m 和 n,求它们的最大公约数 (GCD) 和最小公倍数 (LCM)。程序使用辗转相除法(欧几里得算法)的迭代实现。

01 #include <iostream>
02 using namespace std;
03 
04 int main() {
05     int m, n, a, b, r;
06     cin >> m >> n;
07     a = m;
08     b = n;
09     while (①) {
10         r = m % n;
11         m = ②;
12         n = ③;
13     }
14     cout << "GCD: " << ④ << endl;
15     cout << "LCM: " << ⑤ << endl;
16     return 0;
17 }

  1. ①处应填( ) A. m != 0 B. n != 0 C. r != 0 D. m % n == 0
  2. ②处应填( ) A. n B. r C. a D. b
  3. ③处应填( ) A. m B. r C. a D. b
  4. ④处应填( ) A. n B. r C. m D. a
  5. ⑤处应填( ) A. a * b / m B. a * b / n C. a * b / r D. m * n / a

(3) 高精度加法 输入两个正整数(可能非常大,超过 long long 范围),输出它们的和。 程序使用字符串读取输入,然后转化为数组进行逐位计算。

01 #include <iostream>
02 #include <string>
03 #include <algorithm>
04 using namespace std;
05 
06 int a[505], b[505], c[505];
07 
08 int main() {
09     string s1, s2;
10     cin >> s1 >> s2;
11     int len1 = s1.length();
12     int len2 = s2.length();
13     
14     for (int i = 0; i < len1; i++) a[len1 - 1 - i] = ①;
15     for (int i = 0; i < len2; i++) b[len2 - 1 - i] = s2[i] - '0';
16     
17     int len = len1 > len2 ? len1 : len2;
18     for (int i = 0; i < len; i++) {
19         c[i] += a[i] + b[i];
20         c[i + 1] = ②;
21         c[i] = ③;
22     }
23     
24     if (④) len++;
25     
26     for (int i = len - 1; i >= 0; i--) {
27         cout << ⑤;
28     }
29     cout << endl;
30     return 0;
31 }

  1. ①处应填( ) A. s1[i] B. s1[i] - '0' C. s1[len1 - 1 - i] D. s1[len1 - 1 - i] - '0'
  2. ②处应填( ) A. c[i] % 10 B. c[i] / 10 C. c[i+1] + c[i] / 10 D. a[i] + b[i]
  3. ③处应填( ) A. c[i] / 10 B. c[i] % 10 C. a[i] % 10 D. b[i] % 10
  4. ④处应填( ) A. c[len] > 0 B. c[len] >= 10 C. c[len-1] > 0 D. c[len] != 0
  5. ⑤处应填( ) A. c[i] B. c[len - i] C. a[i] + b[i] D. c[i] + '0'

答案与解析

阅读程序

(1)

  1. × 解析: 程序在循环中每次将 ans 乘以 x 后立即对 10 取模,因此它计算的是 的个位数字,而不是 的值。
  2. √ 解析: 由于每次运算都执行 % 10,结果 ans 必定在 0 到 9 之间。
  3. √ 解析: 输入 2 3,循环执行 3 次。
i=1: ans = 1*2%10 = 2
i=2: ans = 2*2%10 = 4
i=3: ans = 4*2%10 = 8
输出 8。
  1. B 解析: 输入 12 2。
i=1: ans = 1*12%10 = 12%10 = 2
i=2: ans = 2*12%10 = 24%10 = 4
输出 4。
  1. B 解析: 输入 2 10,计算 的个位数。 规律为 2,4,8,6 循环。10 % 4 = 2,所以是第 2 个,即 4。

(2)

  1. × 解析: 变量 count 累加的是 a[i] 的值(count = count + a[i]),而不是个数。它计算的是大于0的偶数之和。
  2. √ 解析: 如果全是负数,a[i] > 0 条件始终不满足,count 保持初始值 0。
  3. × 解析: 如果去掉 a[i] > 0,负偶数也会被加进去,结果会改变。例如输入 -2,原程序加 0,去掉条件后加 -2。
  4. C 解析: 数组 1 2 3 4 5 中,大于0的偶数有 2, 4。和为 2+4=6。
  5. A 解析: 数组 -2 -4 2 4 6 中,大于0的偶数有 2, 4, 6。和为 2+4+6=12。

(3)

  1. × 解析: 程序只是修改字符的值(ASCII码变换),不涉及插入或删除,长度不变。
  2. √ 解析: C, S, P 都是大写,满足第二个 if,加 32 变为小写 c, s, p。
  3. √ 解析: 第一个 if 将小写转大写(-32),第二个 if 将大写转小写(+32)。
  4. C 解析: "Hello"。'H' 是大写 -> 'h'。'e','l','l','o' 是小写 -> 'E','L','L','O'。输出 "hELLO"。
  5. A 解析: s[i] - 32 等价于 s[i] - ('a' - 'A'),即 s[i] - 'a' + 'A'。这是标准的转换方式。

完善程序

(1) 判断回文数

  • 算法思路: 将数字 n 翻转生成新数字 y,比较 n 和 y 是否相等。
  • 解析:
  1. C (n):需要用一个临时变量 t 来操作,保留原数 n 用于最后比较,所以 t 初始化为 n。
  2. B (t % 10):取出 t 的最后一位数字。
  3. A (t / 10):去掉 t 的最后一位数字,以便下一次循环取下一位。
  4. C (n == y):比较原数 n 和翻转后的数 y。
  5. A (1):n=100。 第一次:y=0+0=0, t=10 第二次:y=0+0=0, t=1 第三次:y=0+1=1, t=0 循环结束,y 为 1。

(2) 最大公约数与最小公倍数

  • 算法思路: 欧几里得算法:gcd(m, n) = gcd(n, m % n),直到 n 为 0,此时 m 即为 GCD。LCM = (a * b) / GCD。
  • 解析:
  1. B (n != 0):循环继续的条件是除数不为 0。
  2. A (n):将原来的除数 n 赋值给被除数 m。
  3. B (r):将余数 r 赋值给除数 n。
  4. C (m):循环结束时 n 为 0,m 存储的是最大公约数。
  5. A (a * b / m):最小公倍数 = 两数之积 / 最大公约数。注意原数保存在 a 和 b 中,m 是计算出的 GCD。