夜雨聆风学习资料网

ARTICLE · 1042278

2026 CSP-J 第一轮 C++ 真题逐题解析|考点 + 技巧 + 避坑指南,一文吃透命题风向

2026 CSP-J 第一轮 C++ 真题逐题解析|考点 + 技巧 + 避坑指南,一文吃透命题风向

刚结束的 2026 CSP-J 第一轮 C++ 考试,整体命题风格延续了 “重基础、考细节、贴模板” 的特点,单选基础题送分但易踩坑,阅读程序全是经典算法变种,完善程序侧重思维推导。

本文给大家逐题拆解,题目、答案完全贴合真题,所有程序题补全完整源代码,解析部分优化补充考场秒杀技巧、易错点提醒和公式速记,不管是估分还是后续备考,都能直接用。


一、单项选择题(共 15 题)

今年单选整体偏基础,覆盖 C++ 语法、进制转换、数据结构、数学原理、算法基础五大模块,陷阱集中在概念细节和边界条件。

第 1 题

题目:下列 C++ 数据类型中,能够精确存储大整数的是( ) A. float B. long long C. double D. int

答案:B

解析

  • 考点
    :数据类型的存储特性
  • int 通常范围是 - 2^31~2^31-1,大约 ±21 亿,无法存储超大整数;
  • float 和 double 属于浮点类型,数值范围大,但本质是近似存储,无法保证每一个整数都精确表示;
  • long long 为 64 位整型,范围约 - 9e18~9e18,可以完整精确存储大整数。

💡 速记:精确存整数选整型,范围不够选 long long;浮点都是近似值。

第 2 题

题目:十六进制数转换为八进制数是( ) A. 1364 B. 1635 C. 1405 D. 1365

答案:D

解析

  • 考点
    :进制转换
  • 考场最快方法:十六进制→二进制→八进制。1 位十六进制对应 4 位二进制,1 位八进制对应 3 位二进制,比先转十进制更高效、不易错。
  • 先将十六进制每一位转 4 位二进制,再从右往左每 3 位分组,对应转换为八进制即可得到结果。

💡 技巧:进制转换跨进制时,二进制是桥梁,比反复除法更快。

第 3 题

题目:执行代码 int a = 7, b = 3; std::cout << a / b * b + a % b; 输出是( ) A. 9 B. 10 C. 7 D. 6

答案:C

解析

  • 考点
    :整数除法与取模运算
  • C++ 中整数除法会截断小数部分:7/3 = 2(不是 2.333);
  • 代入计算:2*3 + 7%3 = 6 + 1 = 7。
  • 本质上,对任意整数 a,b,都有 a = (a/b)*b + a%b,这是整数除法的基本性质。

💡 避坑:千万别按实数除法算成 7,很多同学上来就 7/3≈2.33,一步错步步错。

第 4 题

题目:初始栈为空,将元素依次入栈,允许随时出栈。下列出栈序列不可能出现的是( ) A. 略 B. 略 C. 略 D. 略

答案:C

解析

  • 考点
    :栈 “后进先出” 的核心性质
  • 判断原则:如果某个元素先出栈,说明它之前入栈的元素都还在栈里,后续出栈必须按逆序出来,不能跳过栈顶元素。
  • 选项 C 中出现了跳过栈顶元素直接出栈的情况,违反栈的规则,因此不可能。

💡 速记:出栈序列中,任意元素前面比它小的序号,必须是逆序排列。

第 5 题

题目:一棵有 99 个结点的完全二叉树,叶子结点个数是( ) A. 49 B. 50 C. 64 D. 51

答案:B

解析

  • 考点
    :完全二叉树结点性质
  • 核心公式:任意二叉树 n0 = n2 + 1(叶子数 = 度为 2 的结点数 + 1);
  • 完全二叉树中度为 1 的结点最多 1 个。99 是奇数,说明没有度为 1 的结点,因此 n0 + n2 = 99,联立公式得 n0 = 50。

💡 结论秒记:n 个结点的完全二叉树,叶子数 = ⌈n/2⌉,99 个结点直接得 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

解析

  • 考点
    :容斥原理
  • 题目求 1~100 中能被 3 或 5 整除的数之和,直接用容斥:
    1. 3 的倍数和 + 5 的倍数和 - 15 的倍数和(重复计算的部分);
    2. 分别用等差数列求和公式计算,最终结果为 2418。

💡 提醒:看到 “或” 就想到容斥,加两次的要减回来。

第 7 题

题目:上楼梯每次可走 1 级、2 级或 3 级,走到第 10 级台阶共有多少种走法( ) A. 44 B. 121 C. 149 D. 81

答案:D

解析

  • 考点
    :动态规划递推
  • 设 dp [i] 为走到第 i 级的方法数,最后一步可以走 1、2、3 级,因此递推式:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
  • 初始条件:dp [0]=1,dp [1]=1,dp [2]=2,逐步计算到 dp [10] 即可。

💡 速记:爬楼梯类问题,看一步能走几级,就前几项相加。

第 8 题

题目:网格中从起点出发进行 BFS,访问顺序为上、下、左、右。终点第一次入队时,共有多少个格子进入过队列( ) A. 15 B. 12 C. 14 D. 13

答案:C

解析

  • 考点
    :BFS 广度优先搜索的入队规则
  • BFS 的核心规则:结点第一次入队时就标记为已访问,不是出队时才标记;
  • 按题目规定的方向逐层模拟扩展,统计到终点入队时,累计共有 14 个格子进入过队列。

💡 避坑:很多同学以为出队才算访问,算出来就会少算,这是 BFS 最经典的坑。

第 9 题

题目:满足条件的正整数 x 共有多少个( ) A. 8 B. 6 C. 4 D. 5

答案:B

解析

  • 考点
    :最大公约数、互质判断
  • 先对条件化简,转化为求指定区间内与某个数互质的数的个数;
  • 枚举区间内的数,逐一判断最大公约数是否为 1,最终共 6 个满足条件。

第 10 题

题目:硬币面值为 1 元、5 元、10 元,凑出 18 元最少需要多少枚硬币( ) A. 3 B. 4 C. 5 D. 2

答案:A

解析

  • 考点
    :贪心算法
  • 本题面值组合满足贪心策略,优先用大面值,最少 3 枚即可凑出,且任意两枚都无法组成目标数值,因此最少为 3 枚。

💡 提醒:不是所有硬币都能用贪心,只有面值满足倍数关系才可以。

第 11 题

题目:执行代码后输出结果是( )

int a[5] = {1, 2, 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 = a+2,p 指向数组第 3 个元素 a [2](值为 5);
  • 第二步:*(p-1) = p[0] + p[2] 等价于 a[1] = a[2] + a[4] = 5+9 = 14
  • 第三步:p[1] = *(a+1) - a[0] 等价于 a[3] = a[1] - a[0] = 14-1 = 13
  • 最终输出 14,13。

💡 技巧:指针题先把所有指针写法都转换成数组下标,就不会乱。

第 12 题

题目:1000 个元素的升序数组,二分法查找最坏情况下需要比较的次数为( ) A. 500 B. 9 C. 11 D. 10

答案:D

解析

  • 考点
    :二分查找的时间复杂度
  • 二分查找最坏比较次数为 ⌈log₂(n+1)⌉;
  • 代入 n=1000,log₂1001≈10,因此最坏 10 次。

💡 速记:1024 个元素最坏 10 次,1000 个接近 10 次。

第 13 题

题目:数组前缀和数组满足条件,给定数值求区间和的值为( ) A. 252 B. 310 C. 58 D. 61

答案:C

解析

  • 考点
    :前缀和公式
  • 核心公式:区间 [l, r] 的和 = pre [r] - pre [l-1];
  • 代入对应数值直接计算即可得到结果 58。

💡 提醒:前缀和公式别记错,是减 pre [l-1] 不是 pre [l]。

第 14 题

题目:数轴上 7 个点,选一个点使距离之和最小,最小值为( ) A. 37 B. 42 C. 40 D. 38

答案:A

解析

  • 考点
    :中位数性质
  • 一维数轴上,使所有点距离之和最小的位置是中位数;
  • 找到 7 个数的中位数,代入计算总距离即可得到 37。

💡 结论秒记:距离和最小找中位数,距离平方和最小找平均数。

第 15 题

题目:无向图有 12 个顶点,其中 8 个顶点度数为 3,其余顶点度数为 2,边数为( ) A. 36 B. 18 C. 17 D. 20

答案:B

解析

  • 考点
    :握手定理
  • 无向图中所有顶点度数之和 = 2 × 边数;
  • 总度数 = 8×3 + (12-8)×2 = 24 + 8 = 32;边数 = 32/2 = 18。

💡 必背:度数和永远是偶数,等于边数两倍。


二、阅读程序题(共 3 道程序)

今年阅读程序三道题梯度明显:第一道二进制统计变种、第二道高精度加法模板、第三道 DFS 超级质数搜索,全是经典算法的变形,吃透模板就能快速判断。

程序(1)二进制位数与 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;
}

程序核心逻辑: 循环中每次将 n 除以 2,相当于删掉二进制最低位;每轮循环 x 都加 1(统计二进制位数),只有最低位为 1 时 y 才加 1(统计 1 的个数)。最终 x = 二进制位数 + 1,y = 二进制中 1 的个数 + 1。

第 16 题

题目:输入为 3 时,程序输出为 3 3。答案:正确解析:3 的二进制是 11,共 2 位,含 2 个 1。x=2+1=3,y=2+1=3,输出 3 3。

第 17 题

题目:若删除偶数分支中的 ++x,则程序输出的两个数一定相等。答案:错误解析:删除后 x 仅在二进制位为 1 时增加,看似和 y 的计数逻辑一致,但实际由于循环边界和初始值的细节,存在不相等的边界情况,因此 “一定相等” 不成立。

第 18 题

题目:输入为非负整数时,输出第一个数一定不小于第二个数。答案:正确解析:x 统计二进制总位数,y 统计 1 的个数,位数一定≥1 的个数,因此 x 始终≥y。

第 19 题

题目:将 while (n>0) 改为 while (n>=0),可能出现的问题是( ) A. 死循环 B. 结果更大 C. 结果更小 D. 无影响答案:A解析:n=0 时 n/2 仍为 0,条件永远满足,程序陷入死循环。

第 20 题

题目:输入为 7 时,输出为( ) A. 3 3 B. 4 2 C. 4 3 D. 5 2答案:C解析:7 的二进制是 111,共 3 位,3 个 1。x=3+1=4,y=3+1=3,输出 4 3。

第 21 题

题目:输入取遍 1~31 所有整数,输出第二个数恰好为 3 的次数为( ) A. 16 B. 30 C. 31 D. 32答案:C解析:要求第二个输出值恰好为指定数值,对应二进制中 1 的个数固定,枚举 1~31 满足条件的数,共 31 个。


程序(2)高精度加法

完整原程序(核心结构):

// 读入两个数字字符串,逆序存入a、b数组
a[i] = input_str[a_len - i - 1] - '0';
b[i] = input_str[b_len - i - 1] - '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];

程序核心逻辑: 将两个数字字符串逆序存入数组,模拟竖式加法逐位相加,处理进位,最后从高位到低位输出。属于初赛最高频的高精度模板题,考点集中在进位、前导零、边界修改。

第 22 题

题目:输入 123 456 时,输出为 0579。答案:正确解析:123+456=579,程序固定多输出一位最高位,因此结果为 0579。

第 23 题

题目:输入不含前导零,输出也一定不含前导零。答案:错误解析:程序固定输出 max_len+1 位,当和没有最高位进位时,第一位就是 0,存在前导零。

第 24 题

题目:删除计算时的 + carry [i],结果一定比原来小。答案:错误解析:如果加法过程中没有产生任何进位,删除 carry 后结果和原来完全相同,因此 “一定更小” 不成立。

第 25 题

题目:输入 12345 678,输出为( ) A. 012923 B. 013023 C. 13023 D. 130230答案:B解析:12345+678=13023,程序多输出一位前导零,结果为 013023。

第 26 题

题目:进位条件改为 > 10,输入 95 15 时输出为( ) A. 01010 B. 110 C. 140 D. 1410答案:A解析:条件改成大于 10 才进位,个位 5+5=10 不触发进位,十位 9+1=10 也不触发进位,数组直接保存数值,最终输出 01010。

第 27 题

题目:两个 n 位正整数,和小于 10^n,则输出一定满足( ) A. 第一位不为 0 B. 长度一定为 n C. 长度为 n+1,第一位为 0 D. 长度可能为 n答案:C解析:和小于 10^n 说明最高位无进位,但程序仍会输出第 n+1 位,该位为 0,因此长度为 n+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;
}

程序核心逻辑: 递归搜索,每次在数字末尾追加一位 0~9,先判断当前数是不是质数,是质数就继续向下搜索,否则直接返回。最终输出所有前缀都是质数的数(即超级质数),按 DFS 深度优先顺序输出。

第 28 题

题目:输入为 10 时,输出共有 8 行。答案:错误解析:两位且所有前缀均为质数的超级质数数量并非 8 个,实际数量更多,因此说法错误。

第 29 题

题目:输入为 20 时,输出中一定包含 23。答案:正确解析:2 是质数,23 也是质数,且 23≥20,因此一定会被输出。

第 30 题

题目:将循环改为 i 从 1 到 9 步长为 2,输出结果不变。答案:正确解析:大于 2 的偶数都不是质数,因此只枚举奇数结尾不会漏掉任何多位质数,偶数结尾的数会被 check_prime 直接淘汰,不影响结果。

第 31 题

题目:输入为 20 时,输出的第 2 行为( ) A. 23 B. 29 C. 31 D. 239答案:B解析:DFS 按数字从小到大深度优先搜索,先输出 23,第二个输出为 29。

第 32 题

题目:下列说法正确的是( ) A. 输出从小到大排列 B. 输入增大输出行数不增加 C. 每一位只能是 1 或 2 D. 去掉末位后一定是质数答案:D解析

  • A 错误:DFS 是深度优先,不是从小到大排序;
  • B 错误:输入增大,符合条件的数可能增多;
  • C 错误:例如 29 包含数字 9;
  • D 正确:能被递归到的数,它的前缀(删去末位)一定已经通过了质数检查。

第 33 题

题目:输入为 100 时,输出行数为( ) A. 12 B. 13 C. 14 D. 15答案:C解析:枚举所有满足条件、首次≥100 的超级质数,共 14 个。


三、完善程序题(共 2 道)

完善程序是初赛拉分点,核心是先看懂程序意图,再结合上下文变量、语法逻辑排除选项。

第 1 题:进制转换

完整程序(带填空):

// 给定正整数m进制的d位数,转换为n进制
int b[100];
int len = 0;

for (int i = 0; i < d; i++) {
    long long x;
    cin >> x;

    for (int j = len; j >= 1; j--)
        b[j] = ____①____;
    b[0] = ____②____;
    len++;

    for (int j = 0; j < len; j++) {
        if (b[j] >= n) {
            b[j + 1] += ____③____;
            b[j] = ____④____;
            if (j + 1 == len)
                len++;
        }
    }
}

while (____⑤____)
    len--;

程序大意:将一个 m 进制的 d 位数,转换为 n 进制,用数组逆序存储结果,逐位处理进位。

第 34 题 ①处

答案:D解析:新读入一位时,原有数位整体左移一位,每位都要乘以原进制 m,因此b[j] = b[j-1] * m

第 35 题 ②处

答案:B解析:新读入的数位 x 放在最低位,即b[0] = x

第 36 题 ③处

答案:D解析:当前位数值超过 n 时,向高位进位,进位值为b[j] / n

第 37 题 ④处

答案:B解析:进位后当前位保留余数,即b[j] % n

第 38 题 ⑤处

答案:C解析:删除最高位的前导零,从最高位开始判断,为 0 则长度减 1,且至少保留 1 位,因此while(len > 1 && b[len-1] == 0) len--;


第 2 题:平均分割最小极差

完整程序(带填空):

#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;

constexpr int N = 25;
int n, k, a[N];
char s[N];
double ans = 1e100;

int value(char c) {
    return ____①____;
}

void split(int l, int cnt, double mnb, double mxb) {
    if (l > n) {
        if (cnt != 0) return;
        ans = min(ans, mxb - mnb);
        return;
    }
    int sum = 0;
    for (____②____) {
        sum += a[i];
        double nwb = ____③____;
        split(____④____);
    }
}

int main() {
    cin >> n >> k >> s + 1;
    for (int i = 1; i <= n; ++i)
        a[i] = value(s[i]);
    split(____⑤____);
    cout << fixed << setprecision(6) << ans;
}

程序大意:将十六进制字符串分成 k+1 段,计算每段平均值,使平均值的最大值减最小值尽可能小,用 DFS 枚举所有分割方案。

第 39 题 ①处

答案:A解析:十六进制字符转数值,'0'~'9' 减 '0','A'~'F' 减 'A' 加 10,即c <= '9' ? c - '0' : c - 'A' + 10

第 40 题 ②处

答案:B解析:枚举当前段的右端点,从当前左端点 l 开始到 n 结束,因此for(int i = l; i <= n; ++i)

第 41 题 ③处

答案:C解析:计算当前段的平均值,区间长度为 i-l+1,为避免整数除法要转浮点,即1.0 * sum / (i - l + 1)

第 42 题 ④处

答案:D解析:递归下一段,起始位置为 i+1,剩余段数 cnt-1,同时更新最小和最大平均值。

第 43 题 ⑤处

答案:C解析:初始调用从第 1 位开始,分成 k+1 段,最小值初始化为极大值,最大值初始化为极小值,即split(1, k+1, 1e100, -1e100)


四、完整答案速查表

表格

题号
答案
题号
答案
题号
答案
1
B
2
D
3
C
4
C
5
B
6
D
7
D
8
C
9
B
10
A
11
A
12
D
13
C
14
A
15
B
16
17
×
18
19
A
20
C
21
C
22
23
×
24
×
25
B
26
A
27
C
28
×
29
30
31
B
32
D
33
C
34
D
35
B
36
D
37
B
38
C
39
A
40
B
41
C
42
D
43
C
-
-
-
-

五、考点归纳 & 备考建议

核心考点分布

表格

模块
对应题号
核心考点
C++ 基础
1、3、11
数据类型、整数除法、指针运算
进制转换
2、34~38
进制互转、高精度运算
数据结构
4、5
栈的性质、完全二叉树公式
数学原理
6、9、14、15
容斥原理、互质、中位数、握手定理
动态规划
7
递推与状态转移
搜索算法
8、28~33
BFS 入队规则、DFS 搜索顺序
二分与前缀和
12、13
二分复杂度、前缀和公式
高精度
22~27
字符串加法、进位处理、前导零
枚举与 DP
39~43
DFS 枚举、区间最值

备考建议

  1. 基础打牢
    :单选失分大多在概念细节,比如数据类型范围、栈的性质、二叉树公式,这些都是送分题,必须记牢;
  2. 模板吃透
    :阅读程序全是经典算法变种,高精度、DFS、DP、二分这些模板,要做到看到代码就知道考什么;
  3. 多练推导
    :完善程序不要靠蒙,结合上下文变量名、程序意图,用排除法逐一验证选项;
  4. 限时训练
    :初赛时间紧,平时练习就要掐时间,培养快速读代码、抓核心的能力。

整体来看,今年 CSP-J 命题稳中有变,基础更细,算法更活,但核心考点没有超纲。扎实练模板、细心做计算,晋级并不难。

相关学习资料