• 分享
  • CSP-J2026初赛答案整理(带题目+答案+解析)

  • @ 2026-9-19 14:03:31

CSP-J 试题与答案详解


一、单项选择题(共 15 题,每题 2 分,共计 30 分)

1. 下列 C++ 数据类型中,能够精确存储 1018+110^{18}+1 这个整数的是( )

A. float B. long long C. double D. int

答案:B

解析: long long 至少 64 位,范围约 −9.2×1018∼9.2×1018-9.2\times10^{18}\sim9.2\times10^{18},可精确存储 1018+110^{18}+1。float/double 是浮点型,不能精确表示;int 通常只有 32 位。


2. 十六进制数 2F5 转换为八进制数是( )

A. 1364 B. 1635 C. 1405 D. 1365

答案:D

解析: 2F5₁₆ = 757₁₀ = 1365₈。也可先转二进制:0010 1111 0101,再三位分组:001 011 110 101 = 1365。


3. 执行下列 C++ 代码,输出是( )

int a = 7, b = 3;
std::cout << a / b * b + a % b;

A. 9 B. 10 C. 7 D. 6

答案:C

解析: 整数运算 a/b = 2,2*3 + 7%3 = 6 + 1 = 7。即 a=⌊a/b⌋⋅b+a mod ba = \lfloor a/b\rfloor\cdot b + a\bmod b。


4. 初始时栈为空,将 1、2、3、4 依次入栈,入栈过程中允许随时出栈。下列出栈序列中不可能出现的是( )

A. 2,4,3,1
B. 1,2,3,4
C. 3,1,2,4
D. 1,4,3,2

答案:C

解析: 要第一个出栈 3,必须 1、2、3 都已入栈,此时栈底到栈顶为 1、2、3,弹出 3 后只能先出 2 再出 1,不可能出现 1 在 2 之前出栈。其余均可构造。


5. 一棵有 100 个结点的完全二叉树,其叶子结点个数是( )

A. 49 B. 50 C. 64 D. 51

答案:B

解析: 完全二叉树中,叶子结点编号从 ⌊n/2⌋+1\lfloor n/2\rfloor+1 到 nn,共 n−⌊n/2⌋=100−50=50n-\lfloor n/2\rfloor = 100-50 = 50 个。


6. 执行下列代码后 s 的值是( )

int s = 0;
for (int i = 1; i <= 100; i++)
    if (i % 3 == 0 || i % 5 == 0)
        s += i;

A. 3048 B. 2733 C. 2318 D. 2418

答案:D

解析: 容斥原理:3 的倍数和 16831683 + 5 的倍数和 10501050 − 15 的倍数和 315315 = 24182418。


7. 上楼梯每步可上 1 级、2 级或 3 级,从地面走到第 8 级台阶共有多少种不同走法( )

A. 44 B. 121 C. 149 D. 81

答案:D

解析: 递推 f(i)=f(i−1)+f(i−2)+f(i−3)f(i)=f(i-1)+f(i-2)+f(i-3),f(0)=1f(0)=1。依次得 1,2,4,7,13,24,44,811,2,4,7,13,24,44,81。


8. BFS 网格题

S..#.
...#.
...#.
##..E
...#.

按"上、下、左、右"顺序 BFS,当 E 第一次入队时,已经入队过的格子(含 S 和 E)共有多少个( )

A. 15 B. 12 C. 14 D. 13

答案:C

解析: 模拟 BFS 过程,E 入队时共访问 14 格。


9. 满足 1≤n≤1001\le n\le100 且 gcd⁡(n,60)=6\gcd(n,60)=6 的正整数 nn 共有多少个( )

A. 8 B. 6 C. 4 D. 5

答案:B

解析: n=6kn=6k 且 gcd⁡(k,10)=1\gcd(k,10)=1,k≤16k\le16。符合条件的 kk:1, 3, 7, 9, 11, 13,共 6 个。


10. 硬币面值为 1、4、6 元,凑出 9 元最少需要多少枚( )

A. 3 B. 4 C. 5 D. 2

答案:A

解析: 4+4+1=94+4+1=9,3 枚。2 枚最多凑 12 但无法凑 9(6+1=7, 6+4=10, 4+4=8)。


11. 指针题

int a[5] = {1, 3, 5, 7, 9};
int *p = a + 2;
*(p - 1) = p[0] + p[2];
p[1] = *(a + 1) - a[0];
cout << a[1] << "," << a[3];

A. 14,13 B. 8,13 C. 14,7 D. 14,2

答案:A

解析: *(p-1)=a[1],此时 p[0]=a[2]=5,p[2]=a[4]=9,故 a[1]=14。随后 *(a+1) 即修改后的 a[1]=14,p[1]=a[3]=14-1=13。输出 14,13。


12. 1000 个互不相同元素的升序数组二分查找,最坏比较次数( )

A. 500 B. 9 C. 11 D. 10

答案:D

解析: ⌈log⁡21000⌉=10\lceil\log_2 1000\rceil = 10(29=512<1000≤1024=2102^9=512<1000\le1024=2^{10})。


13. 前缀和 S[i]=3i2+iS[i]=3i^2+i,则 a[10]a[10] 的值是( )

A. 252 B. 310 C. 58 D. 61

答案:C

解析: a[10]=S[10]−S[9]=310−252=58a[10]=S[10]-S[9]=310-252=58。


14. 数轴上 7 个点坐标 1、3、4、7、10、15、20,选整数点 P 使距离和最小,最小距离和是( )

A. 37 B. 42 C. 40 D. 38

答案:A

解析: 奇数个点时,距离和在中位数处最小。7 个点排序后第 4 个为 7,取 P=7:距离和 =6+4+3+0+3+8+13=37=6+4+3+0+3+8+13=37。也可枚举验证:P=6 或 8 时为 38,P=5 或 9 时为 39,均更大。


15. 无向图 10 个顶点,4 个度为 3,其余 6 个度为 4,边数是( )

A. 36 B. 18 C. 17 D. 20

答案:B

解析: 握手定理:2E=4×3+6×4=362E = 4\times3+6\times4=36,E=18E=18。


二、阅读程序(共计 40 分)

(1)二进制统计

#include <iostream>
using namespace std;
int main() {
    int n;
    cin >> n;
    int x = 1, y = 1;
    while (n > 0) {
        if (n % 2 == 0) {
            ++x;
        } else {
            ++x;
            ++y;
        }
        n = n / 2;
    }
    cout << x << ' ' << y << endl;
    return 0;
}

程序功能:每次循环处理二进制最低位,xx 每次循环都加 1(即 x=1+x=1+ 二进制位数),yy 在奇数位(即二进制 1)时加 1(即 y=1+y=1+ 二进制中 1 的个数)。

16. 输入 3 时输出 3 3。(√)

解析:3 的二进制为 11,两次循环均为奇数,x=3,y=3x=3,y=3。

17. 将第 11 行的 ++x; 删除后,输出的两个数一定相等。(×)

解析:第 11 行是 else 分支中的 ++x。删除后偶数位只加 xx、奇数位只加 yy。反例 n=5n=5(二进制 101):x=4,y=3x=4,y=3,不相等。

18. 输出的第一个数一定不小于第二个数。(√)

解析:x=1+x=1+ 位数,y=1+y=1+ 1 的个数,位数 ≥ 1 的个数恒成立。

19. while (n > 0) 改为 while (n >= 0) 后可能出现的问题是(A)

A. 陷入死循环 B. 输出比原来大 C. 输出比原来小 D. 不受影响

解析:n=0n=0 时 0/2=00/2=0,条件恒真,死循环。

20. 输入 6 时输出为(C)

A. 3 3 B. 4 2 C. 4 3 D. 5 2

解析:6(110):偶→x=2x=2;3(11)奇→x=3,y=2x=3,y=2;1 奇→x=4,y=3x=4,y=3。

21. nn 取遍 0∼231−10\sim2^{31}-1,第二个数恰好为 2 的次数为(C)

A. 16 B. 30 C. 31 D. 32

解析:y=2y=2 即二进制中恰有 1 个 1,nn 为 2 的幂:20∼2302^0\sim2^{30} 共 31 个。


(2)高精度加法

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int a[100007], b[100007], c[100007], carry[100007];
string input_str;
int a_len, b_len;
int main() {
    cin >> input_str;
    a_len = input_str.size();
    for (int i = 0; i < a_len; i++)
        a[i] = input_str[a_len - i - 1] - '0';
    cin >> input_str;
    b_len = input_str.size();
    for (int i = 0; i < b_len; i++)
        b[i] = input_str[b_len - i - 1] - '0';
    carry[0] = 0;
    for (int i = 0; i < max(a_len, b_len) + 1; i++) {
        c[i] = a[i] + b[i] + carry[i];
        if (c[i] >= 10) {
            carry[i + 1] = 1;
            c[i] -= 10;
        } else {
            carry[i + 1] = 0;
        }
    }
    for (int i = max(a_len, b_len); i >= 0; i--)
        cout << c[i];
    cout << endl;
    return 0;
}

程序功能:倒序存储两个非负整数,逐位相加并处理进位,从最高位(下标 max_len,可能为 0)开始输出,因此结果可能含前导零。

22. 输入 123 456 时输出为 0579。(√)

解析:和为 579,无进位到第 4 位,c[3]=0c[3]=0,输出 0579。

23. 输入不含前导零,输出也一定不含前导零。(×)

解析:反例即第 22 题:123+456=579 输出 0579。

24. 将 c[i] = a[i] + b[i] + carry[i]; 改为 c[i] = a[i] + b[i]; 后,输出一定比原来小。(×)

解析:改后不进位,如 95+15:原来输出 110,改后 c[0]=10,c[1]=10,c[2]=0c[0]=10,c[1]=10,c[2]=0,输出 01010(数值 1010),反而更大。

25. 输入 12345 678 时输出为(B)

A. 012923 B. 013023 C. 13023 D. 130230

解析:12345+678=1302312345+678=13023,最高位 c[5]=0c[5]=0,输出 013023。

26. if (c[i] >= 10) 改为 if (c[i] > 10) 后,输入 95 15 时输出为(A)

A. 01010 B. 110 C. 140 D. 1410

解析:c[0]=10c[0]=10 不满足 >10>10,不进位,c[0]=10c[0]=10;c[1]=10c[1]=10 同理;c[2]=0c[2]=0。输出 01010。

27. 两个 nn 位正整数(无前导零)且和小于 10n10^n,输出字符串一定满足(C)

A. 首字符不为 '0' B. 长度一定为 nn C. 长度一定为 n+1n+1 且首字符为 '0' D. 长度可能为 n+2n+2

解析:和 <10n<10^n 则无进位到第 n+1n+1 位,c[n]=0c[n]=0,循环输出 n+1n+1 位,首字符为 '0'。


(3)质数 DFS

#include <iostream>
using namespace std;
bool check_prime(int x) {
    if (x <= 1) return false;
    for (int i = 2; i * i <= x; i++)
        if (x % i == 0) return false;
    return true;
}
int n;
void search_result(int x) {
    if (!check_prime(x)) return;
    if (x >= n) {
        cout << x << endl;
        return;
    }
    for (int i = 0; i <= 9; i++)
        search_result(x * 10 + i);
}
int main() {
    cin >> n;
    for (int i = 1; i <= 9; i++) search_result(i);
    return 0;
}

程序功能:DFS 按字典序枚举所有质数,输出第一个 ≥n\ge n 的质数(按 DFS 顺序)。注意:若某质数 x<nx<n,会继续扩展其十进制子树。

28. 输入 10 时输出共有 10 行。(×)

解析:实际输出 9 行:23, 29, 31, 37, 53, 59, 71, 73, 79。

29. 若 nn 不大于 5,输出中一定包含 5。(√)

解析:55 是质数且 5≥n5\ge n(n≤5n\le5),DFS 中 i=5i=5 时必然输出。

30. 若 n>10n>10,将扩展循环改为 for (int i = 1; i <= 9; i += 2) 后输出一定不变。(√)

解析:大于 10 的质数末位只能是 1、3、7、9(偶数和 5 的倍数均非质数),只枚举奇数位不会遗漏。

31. 输入 24 时输出的第 3 行为(B)

A. 23 B. 29 C. 31 D. 239

解析:DFS 顺序中,质数 23 虽 <24<24 但会先扩展出 233、239 输出(第 1、2 行),随后 29 为第 3 行。

32. 说法正确的是(D)

A. 按从小到大排列 B. nn 增大行数一定不增 C. 个位只可能是 3 或 7 D. 每个 ≥10\ge10 的数删去末位后一定是质数

解析:D 正确——能进入输出的数都经过 check_prime,其父节点(删去末位)必为质数。A 错(如 239 在 29 前输出);B 错;C 错(如 29 个位为 9)。

33. 输入 200 时输出行数为(C)

A. 12 B. 13 C. 14 D. 15

解析:输出为 233, 239, 293, 311, 313, 317, 373, 379, 593, 599, 719, 733, 739, 797 共 14 行。


三、完善程序(每小题 3 分,共计 30 分)

(1)进制减半(mn 进制 → n 进制)

核心思路: 读入 mn 进制数的高位到低位,每读一位 xx:A←A⋅mn+xA \leftarrow A\cdot mn + x。在 n 进制数组(低位在前)中,A⋅nA\cdot n 相当于整体左移一位,故先令 b[j] = b[j-1]*m(即乘 mm 后相当于乘了 mnmn),b[0]=x,再统一进位。

34. ① b[j - 1] * m(D)

35. ② x(B)

36. ③ b[j] / n(D)

37. ④ b[j] % n(B)

38. ⑤ len > 1 && b[len - 1] == 0(C)

解析:去除高位前导零,但要保证至少保留一位(A=0A=0 时输出 0)。


(2)平衡分割

核心思路: 递归枚举分段,ll 为当前段起点,rr 从 ll 枚举到 nn,nwbnwb 为当前段平均值,用 mnb/mxb 维护最小/最大平均值。

39. ① c - (c < 'A' ? '0' : 'A' - 10)(B)

解析:数字字符减 '0',字母字符减 'A'-10(即加 10)。

40. ② int r = l; r <= n; ++r(D)

41. ③ sum * 1.0 / (r - l + 1)(C)

42. ④ r + 1, cnt + (r < n), min(mnb, nwb), max(mxb, nwb)(A)

解析:r<nr<n 说明后面还有剩余,切分数 cntcnt 加 1;更新最小/最大值。

43. ⑤ 1, 0, 1e100, -1e100(D)

解析:从位置 1 开始,初始切分数 0,最小值设极大、最大值设极小。


答案速查表

题号 答案 题号 答案 题号 答案
1 B 6 D 11 A
2 D 7 12 D
3 C 8 C 13 C
4 9 B 14 A
5 B 10 A 15 B
题号 答案 题号 答案 题号 答案
16 √ 22 √ 28 ×
17 × 23 × 29 √
18 √ 24 30
19 A 25 B 31 B
20 C 26 A 32 D
21 27 C 33 C
题号 答案 填入内容
34 D b[j - 1] * m
35 B x
36 D b[j] / n
37 B b[j] % n
38 C len > 1 && b[len - 1] == 0
39 B c - (c < 'A' ? '0' : 'A' - 10)
40 D int r = l; r <= n; ++r
41 C sum * 1.0 / (r - l + 1)
42 A r + 1, cnt + (r < n), min(mnb, nwb), max(mxb, nwb)
43 D 1, 0, 1e100, -1e100

1 条评论

  • 1