2026/4/18 10:12:05
网站建设
项目流程
如何做exo网站,上海闵行网站制作公司,大连关键词排名系统,校园网站建设调查问卷欢迎大家订阅我的专栏#xff1a;算法题解#xff1a;C与Python实现#xff01; 本专栏旨在帮助大家从基础到进阶 #xff0c;逐步提升编程能力#xff0c;助力信息学竞赛备战#xff01;
专栏特色 1.经典算法练习#xff1a;根据信息学竞赛大纲#xff0c;精心挑选…欢迎大家订阅我的专栏算法题解C与Python实现本专栏旨在帮助大家从基础到进阶 逐步提升编程能力助力信息学竞赛备战专栏特色1.经典算法练习根据信息学竞赛大纲精心挑选经典算法题目提供清晰的代码实现与详细指导帮助您夯实算法基础。2.系统化学习路径按照算法类别和难度分级从基础到进阶循序渐进帮助您全面提升编程能力与算法思维。适合人群准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生希望系统学习C/Python编程的初学者想要提升算法与编程能力的编程爱好者附上汇总贴历年CSP-J初赛真题解析 | 汇总_热爱编程的通信人的博客-CSDN博客单项选择题第1题计算机语言与算法以下不属于面向对象程序设计语言的是 。A.CB.PythonC.JavaD.C【答案】D【解析】C语言面向过程不面向对象第2题基本常识以下奖项与计算机领域最相关的是 。A.奥斯卡奖B.图灵奖C.诺贝尔奖D.普利策奖【答案】B【解析】奥斯卡奖是电影界的普利策奖是摄影方面的第3题数据表示与计算目前主流的计算机储存数据最终都是转换成 数据进行储存。A.二进制B.十进制C.八进制D.十六进制【答案】A【解析】主流计算机都是将数据转换为二进制进行存储的因为二进制最容易实现利用高低电平就可以体现0和1。ENIAC是十进制计算机第4题排序以比较作为基本运算在N个数中找出最大数最坏情况下所需要的最少的比较次数为 。A.N^2B.NC.N-1D.N1【答案】C【解析】最坏的情况需要进行相邻比较如1与2、1与3、1与4…、1与n即N-1次第5题栈和队列对于入栈顺序为abcde的序列下列 不是合法的出栈序列。A.abcdeB.edcbaC.bacdeD.cdaeb【答案】D【解析】A是合法的如进入栈后就出来B是合法的就是5个元素全部入栈后再依次出来C是合法的可以模拟出来D是非法的a出不来因为此时栈顶为b出栈序列中的每个数的序号后面的序号比它小的数是按递减排列的可将a/b/c/d/e转为1/2/3/4/5后检查第6题树对于有n个顶点、m条边的无向连通图mn需要删掉 条边才能使其成为一棵树。A.n-1B.m-nC.m-n-1D.m-n1【答案】D【解析】n个节点的树有n-1条边所以需要删除m-(n-1)条边选D第7题数据表示与计算二进制数101.11对应的十进制数是 。A.6.5B.5.5C.5.75D.5.25【答案】C【解析】1 ∗ 2 2 0 ∗ 2 1 1 ∗ 2 0 1 ∗ 2 − 1 1 ∗ 2 − 2 5.75 1*2^20*2^11*2^01*2^{-1}1*2^{-2} 5.751∗220∗211∗201∗2−11∗2−25.75第8题树如果一棵二叉树只有根结点那么这棵二叉树高度为1。请问高度为5的完全二叉树有 种不同的形态A.16B.15C.17D.32【答案】A【解析】去掉满二叉树右下角的节点后的树就是完全二叉树即若给所有节点编号完全二叉树中逐层遍历的所有节点的编号是连续的。高度为5时第5层可以有16个叶子节点可以删除0-15个叶子节点共16种形态第9题栈和队列表达式a*(bc)*d的后缀表达式为 其中“*”和“”是运算符。A.**abcdB.abc*d*C.abcd**D.*a*bcd【答案】B【解析】中缀表达式转为后缀表达式可以使用1.加括号a ∗ ( b c ) ∗ d − − ( ( a ∗ ( b c ) ) ∗ d ) a*(bc)*d -- ((a*(bc))*d)a∗(bc)∗d−−((a∗(bc))∗d)2.将运算符移到每对运算式的右边( ( a ( b c ) ) ∗ d ) ∗ ((a(bc))*d)*((a(bc))∗d)∗3.去括号a b c ∗ d ∗ abc*d*abc∗d∗第10题组合学6个人两个人组一队总共组成三队不区分队伍的编号。不同的组队情况有 种。A.10B.15C.30D.20【答案】B【解析】第一队从6人中挑2人C(6,2) 6*5/2 15第二队从4人中挑2人C(4,2) 4*3/2 6第三队从2人中挑2人C(2,2) 2*1/2 1如果15 * 6 * 1 90则是有顺序的挑法所以需要去掉3支队伍的不同排列数A(3,3)所以90 / A(3,3) 15第11题树在数据压缩编码中的哈夫曼编码方法在本质上是一种 的策略。A.枚举B.贪心C.递归D.动态规划【答案】B【解析】哈夫曼编码本质上是哈夫曼树的一个应用。哈夫曼树构造就是给定N个带权值的叶子节点构造出一个带权路径长度最小的二叉树。如果想要带权路径长度最小我们应该将权值越小的节点放在越底层因为这些节点路径长度比较长权值小点这样计算出来的带权路径长度就较小。这个其实就是基于贪心的策略。第12题组合学由11223这五个数字组成不同的三位数有 种。A.18B.15C.12D.24【答案】A【解析】假设三位数是abc按照如下计算共18种不同的数字a1 b1 c2/3 2种 b2 c1/2/3 3种 b3 c1/2 2种 a2 b1 c1/2/3 3种 b2 c1/3 2种 b3 c1/2 2种 a3 b1 c1/2 2种 b2 c1/2 2种第13题C语言基础考虑如下递归算法solve(n) if n1 return 1 else if n5 return n*solve(n-2) else return n*solve(n-1)则调用solve(7) 得到的返回结果为 。A.105B.840C.210D.420【答案】C【解析】列出递推矩阵得到结果为210选Ci 0 1 2 3 4 5 6 7 f(i) 1 1 2*f(1)2 3*f(2)6 4*f(3)24 5*f(3)30 6*f(4)144 7*f(5)210第14题图以a为起点对右边的无向图进行深度优先遍历则b、c、d、e四个点中有可能作为最后一个遍历到的点的个数为 。A.1B.2C.3D.4【答案】B【解析】列出所有深度优先遍历的结果abdceacdbeacedb所以作为最后一个遍历到的点的个数有2个分别是b和e第15题应用数学有四个人要从A点坐一条船过河到B点船一开始在A点。该船一次最多可坐两个人。已知这四个人中每个人独自坐船的过河时间分别为1248且两个人坐船的过河时间为两人独自过河时间的较大者。则最短 时间可以让四个人都过河到B点包括从B点把船开回A点的时间A.14B.15C.16D.17【答案】B【解析】使用贪心策略第一条就是希望过河时间最长的人少来回过去后就不要再回来了。第二条就是希望把船开回来的人的时间尽可能短。画个模拟图1248 A --------- B 48 A ---12--- B 48 A ---1---- B 2 1 A ---48--- B 2 1 A ---2---- B 48 A ---12--- B 48最短的时间2182215阅读程序#include iostream using namespace std; int n; int a[1000]; int f(int x) //统计x转为二进制后1的个数 { int ret 0; for (; x; x x - 1) ret; return ret; } int g(int x) //获取x转为二进制后1的最低位 { return x -x; } int main() { cin n; for (int i 0; i n; i) cin a[i]; for (int i 0; i n; i) cout f(a[i]) g(a[i]) ; cout endl; return 0; }第16题输入的n等于1001时程序不会发生下标越界。 A.正确B.错误【答案】B【解析】a[1000]的下标范围为a[0] - a[999]所以a[1000]会导致越界第17题输入的a[i]必须全为正整数否则程序将陷入死循环。 A.正确B.错误【答案】B【解析】尝试将一个负数带入运算f函数的二进制运算逻辑没有发生变化也不会陷入死循环。另外第21题就有负数输入第18题当输入为“5 2 11 9 16 10”时输出为“3 4 3 17 5”。 A.正确B.错误【答案】B【解析】输入数据后逐个计算输出为3 4 3 17 4第19题当输入为“1 511998”时输出为“18”。 A.正确B.错误【答案】A【解析】511998转为二进制后为0111 1100 1111 1111 1110计算的结果为18所以是对的第20题将源代码中g函数的定义14-17行移到main函数的后面程序可以正常编译运行。 A.正确B.错误【答案】B【解析】运行main函数时如果g函数未被声明是无法调用的第21题当输入为“2 -65536 2147483647”时输出为 。A.“65532 33”B.“65552 32”C.“65535 34”D.“65554 33”【答案】B【解析】2147483647换算为二进制后是2^31-1即有31个1所以输出为32选B#include iostream #include string using namespace std; char base[64]; char table[256]; void init() { for (int i0; i26; i) base[i] A i; //10-13行是为了给每个字符标记一个唯一的数字 for (int i0; i26; i) base[26i] a i; for (int i0; i10; i) base[52i] 0 i; base[62] , base[63] /; for (int i0; i256; i) table[i] 0xff; for (int i0; i64; i) table[base[i]] i; table[] 0; } string decode(string str) { string ret; int i; for (i0; istr.size(); i4) { //将4个6位二进制变成3个8位二进制 ret table[str[i]] 2 | table[str[i1]] 4; //i的6位 i1的前2位 if (str[i2] ! ) ret (table[str[i1]] 0x0f) 4 | table[str[i2]] 2; //i1的后4位 i2的前4位 if (str[i3] ! ) ret table[str[i2]] 6 | table[str[i3]]; //i2的后2位 i3的6位 } return ret; } int main() { init(); cout int(table[0]) endl; string str; cin str; cout decode(str) endl; return 0; }第22题输出的第二行一定是由小写字母、大写字母、数字和“”、“/”、“”构成的字符串。 A.正确B.错误【答案】B【解析】算出来的结果可以是256(2^8)以内的任何一个值有可能为空格第23题可能存在输入不同但输出的第二行相同的情形。 A.正确B.错误【答案】A【解析】超出ASCII集后可能会重复第24题输出的第一行为“-1”。 A.正确B.错误【答案】A【解析】11111111在char中就是-1强转成int还是-1第25题设输入字符串长度为ndecode函数的时间复杂度为 A.O(n^(1/2))B.O(n)C.O(nlogn)D.O(n^2)【答案】B【解析】只有一层循环从0循环到n-1第26题当输入为“Y3Nx”时输出的第二行为 。A.“csp”B.“csq”C.“CSP”D.“Csp”【答案】B【解析】把字符带进去硬算最后需要截断后8位为113即q第27题当输入为“Y2NmIDIwMjE”时输出的第二行为 。A.“ccf2021”B.“ccf2022”C.“ccf 2021”D.“ccf 2022”【答案】C【解析】每4个字符转成3个字符Y2Nm转成ccfIDIw转成 20MjE中M和j转成1个字符2j和E转成1个字符1。合并起来就是“ccf 2021” 选C#include iostream using namespace std; const int n 100000; const int N n 1; int m; int a[N], b[N], c[N], d[N]; //a[N]标记一个数是不是质数b[N]用来存质数c[N]用来存i的最小质因数的个数d[N]是g[x]连乘积中去除最小质因子连乘积的部分p指最大质因子 int f[N], g[N]; //f[N]用来存i的约数个数g[N]用来存所有约数之和 void init() { f[1] g[1] 1; for (int i2; in; i) { //枚举i if (!a[i]) { // i是质数 b[m] i; //使用数组b存放地i个质数 c[i] 1, f[i] 2; //i的最小质因数数i个数1个。i的约数2个1和i d[i] 1, g[i] i 1; } for (int j0; jmb[j]*in; j) { int k b[j]; //k为当前的质数 a[i*k] 1; //标记质数k的i倍为合数 if (i%k0) { //k是i*k的最小质因子i包括最小质因子kc[i]是k的个数 c[i*k] c[i] 1; // 在c[i]最小质因子k的个数基础上加1 f[i*k] f[i] / c[i*k] * (c[i*k]1); //f[i*k]的最小质因子k比f[i]多1个如2^2变为2^3那么先除以3再乘以4 d[i*k] d[i]; //根据定义连乘积中不包括k连乘积的部分 g[i*k] g[i] * k d[i]; break; } else { // i不能整除k c[i*k] 1; // i不包括最小质因子ki*k的最小质因子k的个数1 f[i*k] 2 * f[i]; // f[i*k]的质因子比f[i]多一个k且个数1所以因数个数为f[i]*(11) d[i*k] g[i]; // i*k比i多一个质因子kd[i*k]是g[i*k]中不包括k连乘积的部分 g[i*k] g[i] * (k1); // 约数和公式 } } } } int main() { init(); int x; cin x; cout f[x] g[x] endl; return 0; }假设输入的x是不超过1000的自然数完成下面的判断题和单选题第28题若输入不为“1”把第13行删去不会影响输出的结果。 A.正确B.错误【答案】A【解析】对代码中所有数组进行暴力打表猜测其作用i2345678910a[ ]001010111b[ ]23571113192329c[ ]112111321d[ ]111141116f[ ]223242434g[ ]347612815131813行对1进行预处理枚举是从2开始全程没有与1相关的数据输出如果输入从2开始就没有影响第29题第25行的“f[i]/c[i*k]”可能存在无法整除而向下取整的情况。 A.正确B.错误【答案】B【解析】f[i]表示i的质因数个数c[i * k]表示i * k的最小质因数个数f[i](num11)(num21)…(numn1)其中numx为质因数c[i * k]c[i]1见代码num11这两个数之间一定是倍数的关系第30题在执行完init() 后f数组不是单调递增的但g数组是单调递增的。 A.正确B.错误【答案】B【解析】约数和不一定是单调递增如g[8]124815g[9]13913第31题init函数的时间复杂度为 A.O(n)B.O(nlogn)C.O(n*n^(1/2))D.O(n^2)【答案】A【解析】欧拉线性筛的特点第32题在执行完init() 后f[1] f[2] f[3] … f[100] 中有 个等于2。A.23B.24C.25D.26【答案】C【解析】只有质数的约数个数为2所以也就是求1-100中有多少个质数有25个选C第33题当输入为“1000”时输出为 。A.“15 1340”B.“15 2340”C.“16 2340”D.“16 1340”【答案】C【解析】10002353约数个数(31)*(31)16。有1000和500两个约数肯定超过1340所以选C完善程序有n个人围成一个圈依次标号0至n-1。从0号开始依次0,1,0,1,…交替报数报到1的人会离开直至圈中只剩一个人。求最后剩下人的编号。试补全模拟程序。#include iostream using namespace std; const int MAXN 1000000; int F[MAXN]; int main() { int n; cin n; int i 0, p 0, c 0; //i是人的编号c是已出队的人数p表示当前要报的数 while (__1__) { if (F[i] 0) { //表示i在队中 if (__2__) { //报了1 F[i] 1; //i出队 __3__; } __4__; } __5__; } int ans -1; for (i0; in; i) if (F[i] 0) //编号为i这个人在队中 ans i; cout ans endl; return 0; }第34题1处应填 A.inB.cnC.in-1D.cn-1【答案】D【解析】题目要求只剩1个人为止反过来说就是还剩大于1个人就继续循环。所以若作为出队人数的c小于n-1人就继续循环。选D第35题2处应填 A.i % 2 0B.i % 2 1C.pD.!p【答案】C【解析】报了1这个数就要出队而p表示当前要报的数所以选C第36题3处应填 A.iB.i (i 1) % nC.cD.p ^ 1【答案】C【解析】上一行表示出队所以这里应该是出队人数1所以选C第37题4处应填 A.iB.i (i 1) % nC.cD.p ^ 1【答案】D【解析】报完数后应该就是要处理下一个要报的数只有D选项是对p要报的数进行操作。110011选D第38题5处应填 A.iB.i (i 1) % nC.cD.p ^ 1【答案】B【解析】这个是要处理下一个要报数的人ii走到n-1后再加1需要通过mod运算变为0。所以选B矩形计数平面上有n个关键点求有多少个四条边都和x轴或者y轴平行的矩形满足四个顶点都是关键点。给出的关键点可能有重复但完全重合的矩形只记一次。试补全枚举算法。#include iostream using namespace std; struct point { int x, y, id; }; bool equals(point a, point b) { return a.x b.x a.y b.y; } bool cmp(point a, point b) { //相当于ab return __1__; } void sort(point A[], int n) { //将关键点的集合按照从小到大方式排序 for ( int i0; in; i) for (int j1; jn; j) if (cmp(A[j], A[j-1])) { point t A[j]; A[j] A[j-1]; A[j-1] t; } } int unique(point A[], int n) { //unique为去重 int t 0; for (int i0; in; i) if (__2__) A[t] A[i]; return t; } bool binary_search(point A[], int n, int x, int y) { //二分搜索判断p是否在A[0]-A[n-1]中 point p; p.x x; p.y y; p.id n; int a 0, b n - 1; while (ab) { int mid __3__; if (__4__) a mid 1; else b mid; } return equals(A[a], p); } const int MAXN 1000; point A[MAXN]; int main() { int n; cin n; for (int i0; in; i) { cin A[i].x A[i].y; A[i].id i; } sort(A, n); n unique(A,n); int ans 0; for (int i0; in; i) for (int j0; in; j) if (__5__ binary_search(A, n, A[i].x, A[j].y) binary_search(A, n, A[j].x, A[i].y)) { ans ; } cout ans endl; return 0; }第39题①处应填 A.a.x ! b.x ? a.x b.x : a.id b.idB.a.x ! b.x ? a.x b.x : a.y b.yC.equals(a, b) ? a.id b.id : a.x b.xD.equals(a, b) ? a.id b.id : (a.x ! b.x ? a.x b.x : a.y b.y)【答案】B【解析】因为equals是比坐标cmp也只能比坐标所有带id的选项都不能选所以只能选B。优先级是先比较x再比较y。第40题②处应填 A.i 0 || cmp(A[i], A[i-1])B.t 0 || equals(A[i], A[t-1])C.i 0 || !cmp(A[i], A[i-1])D.t 0 || !equals(A[i], A[t-1])【答案】D【解析】当A[t-1]不等于A[i]就把A[i]放到A[t]的位置然后t。选D第41题③处应填 A.b - (b - a) / 2 1B.(a b 1) 1C.(a b) 1D.a (b - a 1) / 2【答案】C【解析】二分查找方法有很多种没有必要背下来唯一的标准是不能死循环死循环就是发生在a与b最接近时a与b的差值为1即区间为[a, a1]。此时需要拆为[a]和[a1]这两个区间而二分查找拆成的区间就是[a, mid][mid1, a1]那么推断出mid的值要等于a。可以将ba1代入选C。右移一位相当于除2。第42题④处应填 A.!cmp(A[mid], p)B.cmp(A[mid], p)C.cmp(p, A[mid])D.!cmp(p, A[mid])【答案】B【解析】目的是要淘汰不等于p的部分4个选项只有B选项成立时A[0] … A[mid]不可能等于p因为此处是A[0] … A[mid]小于p第43题⑤处应填 A.A[i].x A[j].xB.A[i].id A[j].idC.A[i].x A[j].x A[i].id A[j].idD.A[i].x A[j].x A[i].y A[j].y【答案】D【解析】A[i]要在A[j]的左下方程序的目标就是要在i点和j点之间通过二分查找找到一个点的坐标等于A[i].x和A[j].y