ARTICLE · 1054459
2026年CSP-J第一轮试题详解(中):阅读程序
备注:依据两份完整试卷独立整理,对照AKCSP、OIerMaster、CSDN和OneCoder等多方资料逐题交叉核验。程序输出、边界条件及争议题另按原卷代码独立推演,力求最大限度减少误差。
截至发文,CCF/NOI尚未公布正式标准答案,最终以官方发布为准。
本篇答案速查
16-21 √ × √ A C C22-27 √ × × B A C28-33 × √ √ B D C
第16至21题:除以2的程序在统计什么
第一段程序读入n,令x=y=1,然后不断执行n=n/2。每轮x都会加1,只有当前n为奇数时y才加1。
因此,对正整数来说,x=二进制位数+1,y=二进制中1的个数+1。先抓住这两个含义,六道题就不必逐句猜。
程序代码
#include<iostream>using namespace std;intmain(){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;}
第16题
当输入为3时,程序输出为3 3。( )
答案
正确
解读
输入3时,二进制是11,循环两轮,两轮都是奇数,最后x=3、y=3。
第17题
将奇数分支中的++x;删除后,程序输出的两个数一定相等。( )
答案
错误
解读
删除奇数分支里的++x后,x只在遇到二进制位0时增加,y只在遇到1时增加,两者当然不一定相等。例如输入1,最终就是1 2。
第18题
假设输入为非负整数,程序输出的第一个数一定不小于第二个数。( )
答案
正确
解读
原程序每轮都让x加1,而y只在部分轮次加1,两者初值又相同,所以始终有x≥y。
第19题
将while (n > 0)改为while (n >= 0)后,程序可能出现的问题是( )。
A. 陷入死循环 B. 输出结果比原来大 C. 输出结果比原来小 D. 输出结果不受影响
答案
A
解读
若条件改成n>=0,当n变为0后,0/2仍是0,循环条件永远成立,程序陷入死循环。
第20题
当输入为6时,输出为( )。
A. 3 3B. 4 2C. 4 3D. 5 2
答案
C
解读
4 3。6的二进制是110,共3位、含2个1,因此输出“位数+1、1的个数+1”,即4 3。
第21题
若输入n依次取遍0,1,2,...,2^31-1,程序输出的第二个数恰好为2的次数是( )。
A. 16 B. 30 C. 31 D. 32
答案
C
解读
31次。第二个数等于2,意味着二进制中恰好有一个1,也就是2的非负整数次幂。在0到2^31-1中,有2^0至2^30,共31个。
第22至27题:高精度加法故意多输出一位
第二段程序把两个十进制整数倒序存入数组,逐位相加并处理进位。算法主体并不陌生,真正的陷阱在输出:它总是从下标max(a_len,b_len)打印到0,因此固定输出“最大位数+1”位。没有最高位进位时,开头就会多一个0。
程序代码
#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;intmain(){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;}
题目说明:两个输入均为非负整数,位数不超过100000,可能包含前导零。
第22题
当输入为123 456时,程序输出为0579。( )
答案
正确
解读
123+456=579,程序固定输出4位,所以结果是0579。
第23题
假设输入的两个数均不含前导零,则程序输出的结果也一定不会含有前导零。( )
答案
错误
解读
即使两个输入都没有前导零,只要相加后没有产生新的最高位,程序仍会打印数组中多出来的那个0。
第24题
将c[i]=a[i]+b[i]+carry[i];改为c[i]=a[i]+b[i];后,程序输出的结果一定比原来的结果小。( )
答案
错误
解读
删除carry[i]会漏掉进位,但结果不一定“严格小于”原结果。比如1+1没有进位,两种写法输出完全相同。
第25题
当输入为12345 678时,输出为( )。
A. 012923B. 013023C. 13023D. 130230
答案
B
解读
013023。12345+678=13023,最大输入长度是5,程序会打印6位,所以前面补出一个0。
第26题
将判断条件c[i]>=10改为c[i]>10后,当输入为95 15时,输出为( )。
A. 01010B. 110C. 140D. 1410
答案
A
解读
01010。把>=10误改为>10后,恰好等于10的某一位不会进位,也不会减10。输入95和15时,两位的c[i]都可能直接保存整数10;cout不会限制每个数组元素只打印一位,最终拼成0、10、10,即01010。
第27题
假设输入的两个数均为n位正整数(不含前导零),且它们的和小于10^n,则程序输出的字符串一定满足( )。
A. 第一个字符一定不为 0B. 长度一定为 nC. 长度为 n+1且第一个字符为0D. 长度可能为 n+2
答案
C
解读
两个n位数的和小于10^n,说明没有新增最高位。程序仍固定打印n+1个位置,所以长度是n+1,首字符为0。
这组题提醒我们:分析程序输出,不能擅自把代码“修正”为正常写法。程序有没有去掉前导零、一个数组元素会不会打印成两位,都要忠实于现有代码。
第28至33题:DFS输出的不是排序结果
第三段程序从1至9依次出发。当前数不是质数就立即返回;若它已经不小于输入的n,就输出并停止向后添加数字;否则依次在末尾添加0至9,继续深度优先搜索。
所以,输出的是一批“从右侧不断删去末位后,沿途仍为质数”的数。程序采用深度优先搜索,先一路向更深处走,再回头尝试下一个分支,输出顺序不等于数值从小到大。
程序代码
#include<iostream>using namespace std;boolcheck_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;voidsearch_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);}intmain(){cin >> n;for (int i = 1; i <= 9; i++)search_result(i);return 0;}
第28题
当输入为10时,程序的输出共有10行。( )
答案
错误
解读
输入10时,输出23、29、31、37、53、59、71、73、79,一共9行,不是10行。
第29题
若输入的n不大于5,则程序的输出中一定包含5。( )
答案
正确
解读
当n≤5时,主程序调用search_result(5),5是质数且已经满足5≥n,因此一定会输出5。
第30题
若输入的n大于10,将循环改为for (int i=1;i<=9;i+=2)后,程序的输出结果一定不变。( )
答案
正确
解读
当n>10时,继续扩展的是多位质数。多位质数的末位不可能是偶数或5,因此只尝试1、3、5、7、9不会漏掉原本能够通过质数检查的分支。
第31题
当输入为24时,程序输出的第3行是( )。
A. 23 B. 29 C. 31 D. 239
答案
B
解读
第3行是29。输入24后,搜索先从23继续向下,依次输出233、239,回溯后才输出29。因此前三行是233、239、29,不能按大小排序想成23、29、31。
第32题
下列关于该程序输出的说法中,正确的是( )。
A. 输出的数一定从小到大排列 B. 随着输入 n增大,输出行数一定不会增加C. 输出数的个位只可能是3或7 D. 输出的每个不小于10的数,删去十进制末位后得到的数一定是质数
答案
D
解读
每个被输出的多位数都来自某个已经通过质数检查的前缀,所以删去最后一位后,得到的数一定是质数。A错在DFS并非升序;B错在阈值增大后可能继续搜索出更多后代;C错在个位也可能是1或9。
第33题
当输入为200时,程序输出的行数为( )。
A. 12 B. 13 C. 14 D. 15
答案
C
解读
14行。输入200时可按首位分支统计:从2出发有233、239、293共3个;从3出发有311、313、317、373、379共5个;从5出发有593、599共2个;从7出发有719、733、739、797共4个,总数3+5+2+4=14。
小结
三段程序最典型的陷阱分别是初值多出的1、高精度程序固定多打印一位,以及DFS输出顺序并非数值升序。看懂功能只是第一步,把边界和输出顺序算到底才是得分点。下一篇将详解两段完善程序。