欢迎大家订阅我的专栏:算法题解:C++与Python实现!
本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战!
专栏特色
1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的代码实现与详细指导,帮助您夯实算法基础。
2.系统化学习路径:按照算法类别和难度分级,从基础到进阶,循序渐进,帮助您全面提升编程能力与算法思维。
适合人群:
- 准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生
- 希望系统学习C++/Python编程的初学者
- 想要提升算法与编程能力的编程爱好者
附上汇总贴:历年CSP-J初赛真题解析 | 汇总_热爱编程的通信人的博客-CSDN博客
单项选择
第1题
在8位二进制补码中,10101011表示的数是十进制下的( )。
A.43
B.-85
C.-43
D.-84
【答案】:B
【解析】
正数的原码、反码和补码均相同
最高位为符号位,0表示正数,1表示负数。
负数的反码:原码符号位不变,其他位取反
负数的补码:反码+1
计算得到原码为11010101,为-85
第2题
计算机存储数据的基本单位是( )。
A.bit
B.Byte
C.GB
D.KB
【答案】:B
【解析】
2013年就讲过,基本单位是字节,最小单位是bit
第3题
下列协议中与电子邮件无关的是( )。
A.POP3
B.SMTP
C.WTO
D.IMAP
【答案】:C
【解析】
WTO是世界贸易组织
POP3 Post office Protocol 3
第4题
分辨率为800x600、16位色的位图,存储图像信息所需的空间为( )。
A.937.5KB
B.4218.75KB
C.4320KB
D.2880KB
【答案】:A
【解析】
800 * 600 * 16 / 8 / 1024 = 937.5KB
第5题
计算机应用的最早领域是( )。
A.数值计算
B.人工智能
C.机器人
D.过程控制
【答案】:A
【解析】
计算机常识,最早就用于计算导弹射击路线
第6题
下列不属于面向对象程序设计语言的是( )。
A.C
B.C++
C.Java
D.C#
【答案】:A
【解析】
2014年介绍过面向对象程序设计语言,C语言没有对象(单身狗)
第7题
NOI的中文意思是( ) 。
A.中国信息学联赛
B.全国青少年信息学奥林匹克竞赛
C.中国青少年信息学奥林匹克竞赛
D.中国计算机协会
【答案】:B
【解析】
信奥常识,NOI National Olympiad in Informatics
第8题
2017年10月1日是星期日,1999年10月1日是( )。
A.星期三
B.星期日
C.星期五
D.星期二
【答案】:C
【解析】
非闰年365天,365%7=1,每过一年,相当于星期中过了一天;闰年366天,366%7==2,每过一年,相当于星期中过了两天。1999年->2017年一共18年(5个闰年,13个非闰年),相当于星期中过了23天,23%7==2。星期五过2天是星期日,选C
第9题
甲、乙、丙三位同学选修课程,从4门课程中,甲选修2门,乙、丙各选修3门,则不同的选修方案共有( )种。
A.36
B.48
C.96
D.192
【答案】:C
【解析】
甲从4门中选2门:\(C_{4}^{2}\)
乙从4门中选3门:\(C_{4}^{3}\)
丙从4门中选3门:\(C_{4}^{3}\)
6*4*4=96
第10题
设G是有n个结点、m条边(n≤m)的连通图,必须删去G的( )条边,才能使得G变成一棵树。
A.m-n+1
B.m-n
C.m+n+1
D.n-m+1
【答案】:A
【解析】
一棵树n个节点则有n-1条边。m - x = n - 1,得到x = m - n + 1
第11题
对于给定的序列{ak},我们把(i, j)称为逆序对当且仅当i<j且ai>aj。那么序列1,7,2,3,5,4的逆序对数为( )个。
A.4
B.5
C.6
D.7
【答案】:B
【解析】
(7,2) (7,3) (7,5) (7,4) (5,4)共5对
第12题
表达式\(a*(b+c)*d\)的后缀形式是( )。
A.\(abcd*+*\)
B.\(abc+*d*\)
C.\(a*bc+*d\)
D.\(b+c*a*d\)
【答案】:B
【解析】
正常的运算对应中缀形式,可以画出二叉树,写出后续遍历结果,即后缀形式,选B
第13题
向一个栈顶指针为hs的链式栈中插入一个指针s指向的结点时,应执行( )。
A.hs->next=s;
B.s->next=hs; hs=s;
C.s->next=hs->next; hs->next=s;
D.s->next=hs; hs=hs->next;
【答案】:B
【解析】
先把栈顶变成s所指向的节点,即s->next = hs。再把指针s变为栈顶,即hs = s;
第14题
若串S="copyright", 其子串的个数是( ) 。
A.72
B.45
C.46
D.36
【答案】:C
【解析】
(1+9) * 9 / 2 = 45,再加1个空串
第15题
十进制小数13.375对应的二进制数是( )。
A.1101.011
B.1011.011
C.1101.101
D.1010.01
【答案】:A
【解析】
小数部分,乘2取整,剩余部分继续乘2取整。0.375=0.25+0.125=1/4+1/8
第16题
对于入栈顺序为a,b,c,d,e,f,g的序列,下列( )不可能是合法的出栈序列。
A.a,b,c,d,e,f,g
B.a,d,c,b,e,g,f
C.a,d,b,c,g,f,e
D.g,f,e,d,c,b,a
【答案】:C
【解析】
C错误是因为不可能b先出,c再出
第17题
设A和B是两个长为n的有序数组,现在需要将A和B合并成一个排好序的数组,任何以元素比较作为基本运算的归并算法在最坏情况下至少要做( )次比较。
A.\(n^2\)
B.nlogn
C.2n
D.2n-1
【答案】:D
【解析】
一共2n个数,最坏情况需要比较2n-1次(最后一个数不用比较)
第18题
从( )年开始, NOIP竞赛将不再支持Pascal语言。
A.2020
B.2021
C.2022
D.2023
【答案】:C
【解析】
NOI常识
第19题
一家四口人,至少两个人生日属于同一月份的概率是( )(假定每个人生日属于每个月份的概率相同且不同人之间相互独立)。
A.1/12
B.1/144
C.41/96
D.3/4
【答案】:C
【解析】
至少两人属于同一月份的方面是四个人的生日都不在同一月份,概率为\((12*11*10*9)/(12*12*12*12)=55/96\),答案为41/96
第20题
以下和计算机领域密切相关的奖项是( )。
A.奥斯卡奖
B.图灵奖
C.诺贝尔奖
D.普利策奖
【答案】:B
【解析】
2015年已经考过,计算机届最高奖项是图灵奖
问题求解
第21题
一个人站在坐标(0, 0)处,面朝x轴正方向。第一轮,他向前走1单位距离,然后右转;第二轮,他向前走2单位距离,然后右转;第三轮,他向前走3单位距离,然后右转......他一直这么走下去。请问第2017轮后,他的坐标是:( )( )。

【答案】:1009 1008
【解析】
第0轮:(0,0)
第1轮:(1,0),第2轮:(1,-2),第3轮:(-2,-2),第4轮:(-2,2)
第5轮:(3,2),第6轮:(3,-4),第7轮:(-4,-4),第8轮:(-4,4)
第9轮:(5,4),第10轮:(5,),第11轮:(-2,-2),第12轮:(-2,2)
每4轮行走方向一样,2017%4=1,第2017轮:(1009,1008)
第22题
如下图所示,共有13个格子。对任何一个格子进行一次操作,会使得它自己以及与它上下左右相邻的格子中的数字改变(由1变0,或由0变1)。现在要使得所有的格子中的数字都变为0,至少需要( )次操作。

【答案】:3
【解析】
自己模拟,第一次改变最顶上的1,第二次改变右边倒数第2个0,第三次改变中间的1
阅读程序
#include <iostream>
using namespace std;
int main()
{int t[256];string s;int i;cin >> s;for (i=0; i<256; i++)t[i] = 0;for (i=0; i<s.length(); i++)t[s[i]]++;for (i=0; i<s.length(); i++)if (t[s[i]]==1){cout << s[i] << endl;return 0;}cout << "no" << endl;return 0;
}
第23题
输入:xyzxyw
输出:( )
【答案】:z
【解析】
程序的功能是输出第一个只出现1次的字母7845690-23978-6=
#include <iostream>
using namespace std;int g(int m, int n, int x)
{int ans = 0;int i;if (n==1)return 1;for (i=x; i<=m/n; i++) ans += g(m-i, n-1, i);return ans;
}int main()
{int t, m, n;cin >> m >> n;cout << g(m, n, 0) << endl;return 0;
}
第24题
输入:7 3
输出:( )
【答案】:8
【解析】
g(7,3,0)=g(7,2,0)+g(6,2,1)+g(5,2,2)
g(7,2,0)=g(7,1,0)+g(6,1,1)+g(5,1,2)+g(4,1,3)=4
g(6,2,1)=g(5,1,1)+g(4,1,2)+g(3,1,3)=3
g(5,2,2)=g(3,1,2)=1
所以g(7,3,0)=8
求排列组合的题,m+x==m的方案数
#include <iostream>
using namespace std;int main()
{string ch;int a[200];int b[200];int n, i, t, res;cin >> ch;n = ch.length();for (i=0; i<200; i++)b[i] = 0;for (i=1; i<=n; i++){a[i] = ch[i-1] - '0';b[i] = b[i-1] + a[i];}res = b[n];t = 0;for (i=n; i>0; i--){if (a[i]==0)t++;if (b[i-1]+t<res)res = b[i-1] + t;}cout << res << endl;return 0;
}
第25题
输入:1001101011001101101011110001
输出:( )
【答案】:11
【解析】
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ch | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | |
| a[ ] | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
| b[ ] | 0 | 1 | 1 | 1 | 2 | 3 | 3 | 4 | 4 | 5 | 6 | 6 | 6 | 7 | 8 | 8 | 9 | 10 | 10 | 11 | 11 | 12 | 13 | 14 | 15 | 15 | 15 | 15 | 16 |
| t | 12 | 12 | 11 | 10 | 10 | 10 | 9 | 9 | 8 | 8 | 8 | 7 | 6 | 6 | 6 | 5 | 5 | 5 | 4 | 4 | 3 | 3 | 3 | 3 | 3 | 2 | 1 | 0 | |
| res | 11 | 12 | 13 | 14 | 15 |
b数组是在算从头到i的“1”的个数(前缀和),res为a数组中1的个数,t是从i到尾的“0”的个数(后缀和)。
程序的目的是将字符串劈成两半,前一半统计1的个数,后一半统计0的个数,计算什么时候得到的两者的个数最小。
#include <iostream>
using namespace std;
int main()
{int n, m;cin >> n >> m;int x=1;int y=1;int dx=1;int dy=1;int cnt = 0;while (cnt != 2){cnt = 0;x = x + dx;y = y + dy;if (x==1 || x == n) {++cnt;dx = -dx;}if (y==1 || y==m){++cnt;dy = -dy;}}cout << x << " " << y << endl;return 0;
}
第26题
输入1:4 3
输出1:( )
输入2:2017 1014
输出2:( )
【答案】:1 3 和2017 1
【解析】
| x | y | dx | dy | cnt |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 0 |
| 2 | 2 | 1 | 1 | 0 |
| 3 | 3 | 1 | -1 | 0/1 |
| 4 | 2 | -1 | -1 | 0/1 |
| 3 | 1 | -1 | 1 | 0/1 |
| 2 | 2 | -1 | 1 | 0 |
| 1 | 3 | 1 | -1 | 0/1/2 |
两个if语句都成立,才能结束while循环。(n-1)和(m-1)的最小公倍数。2017和2014的最小公倍数是2016 * 1013,即x走1013次,y走2016次,则1013为奇数,所以x到了2017,2016为偶数,所以y到了1
完善程序
(快速幂)请完善下面的程序,该程序使用分治法求\(x^p\ mod\ m\)的值。
输入:三个不超过10000的正整数x,p,m。
输出:\(x^p\ mod\ m\)的值。
提示:若p为偶数,\(x^p=(x^2)^{p/2}\);若p为奇数,\(x^p=x*(x^2)^{(p-1)/2}\)。
#include <iostream>
using namespace std;int x, p, m, i, result;int main() {cin >> x >> p >> m;result = __1__;while (__2__) {if (p%2==1) result = __3__;p /= 2;x = __4__;}cout << __5__ << endl;return 0;
}
第27题
1处应该填( )
【答案】:1
【解析】
乘法的累乘器初始值为1
第28题
2处应该填( )
【答案】:p>0
【解析】
按照快速幂的公式,最后一个数算到1次方
第29题
3处应该填( )
【答案】:result*x%m
【解析】
如果是奇数,需要保留底数
第30题
4处应该填( )
【答案】:x*x%m
【解析】
最后一定会有个数的1次方出现,所以这里只是x*x%m
第31题
5处应该填( )
【答案】:result
【解析】
仅需输出答案
(切割绳子)有n条绳子,每条绳子的长度已知且均为正整数。绳子可以以任意正整数长度切割,但不可以连接。现在要从这些绳子中切割出m条长度相同的绳段,求绳段的最大长度是多少。
输入:第一行是一个不超过100的正整数n,第二行是n个不超过\(10^6\)的正整数,表示每条绳子的长度,第三行是一个不超过\(10^8\)的正整数m。
输出:绳段的最大长度,若无法切割,输出Failed。
#include <iostream>
using namespace std;int n, m, i, lbound, ubound, mid, count;
int len[100]; // 绳子长度
int main()
{cin >> n;count = 0;for (i=0; i<n; i++){cin >> len[i];__1__;}cin >> m;if (__2__){cout << "Failed" << endl;return 0;}lbound = 1;ubound = 1000000;while (__3__){mid = __4__;count = 0;for (i=0; i<n; i++)__5__;if (count < m)ubound = mid - 1;elselbound = mid;}cout << lbound << endl;return 0;
}
第32题
1处应该填( )
【答案】:count += len[i]
【解析】
计算所有线段的总长
第33题
2处应该填( )
【答案】:count<m
【解析】
如果所有线段加起来的总长度小于m,那么即使按照最小的长度1来切割,也无法切出m段
第34题
3处应该填( )
【答案】:lbound<ubound
【解析】
l和r重合时才退出循环
第35题
4处应该填( )
【答案】:(lbound+ubound+1)/2
【解析】
如果l=3,r=4,且3就是正解,那么应该希望mid = 4,否则就会陷入死循环
第36题
5处应该填( )
【答案】:count += len[i]/mid
【解析】
计算在mid长度下可以切出的总段数