2026/4/3 5:36:49
网站建设
项目流程
金融网站制作,网易企业邮箱可以全部转发么,中信建设有限责任公司世界排名,wordpress 壁纸云欢迎大家订阅我的专栏#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题C语言基础以下哪种功能没有涉及C语言的面向对象特性支持 。A.C中调用printf函数B.C中调用用户定义的类成员函数C.C中构造一个class或structD.C中构造来源于同一基类的多个派生类【答案】A【解析】Aprintf是C语言中的函数C语言是面向过程语言B/C/D选项中均有class所以涉及面向对象特性第2题栈有6个元素按照6、5、4、3、2、1的顺序进入栈S请问下列哪个出栈序列是非法的 。A.543612B.453126C.346521D.234156【答案】C【解析】A/B/D按照6、5、4、3、2、1顺序进栈可以实现该顺序出栈C需要6出栈时6不是栈顶而是5所以无法出栈第3题C语言基础运行以下代码片段的行为是 。int x 101; int y 201; int *p x; int *q y; p q;A.将x的值赋为201B.将y的值赋为101C.将q指向x的地址D.将p指向y的地址【答案】D【解析】Dp q将p也指向y的地址第4题线性表链表和数组的区别包括 。A.数组不能排序链表可以B.链表比数组能存储更多的信息C.数组大小固定链表大小可动态调整D.以上均正确【答案】C【解析】A数组可以排序B不一定数组也可以是结构体数组可以放任意多的信息C数组使用过程中大小不能调整链表每次申请一块内存用这块内存去存一个内容大小可以动态调整第5题栈和队列对假设栈S和队列Q的初始状态为空。存在e1~e6六个互不相同的数据每个数据按照进栈S、出栈S、进队列Q、出队列Q的顺序操作不同数据间的操作可能会交错。已知栈S中依次有数据e1、e2、e3、e4、e5和e6进栈队列Q依次有数据e2、e4、e3、e6、e5和e1出队列。则栈S的容量至少是 个数据。A.2B.3C.4D.6【答案】B【解析】依次有e2、e4、e3、e6、e5和e1出队列即表示有e2、e4、e3、e6、e5、e1顺序出栈。栈S最大容量为3即存放e1、e3、e4或e1、e5、e6时需要从栈底到栈顶第6题栈和队列对表达式a(b-c)*d的前缀表达式为 其中、-、*是运算符。A.*a-bcdB.a*-bcdC.abc-d*D.abc-d【答案】B【解析】a(b-c)*d是常见的中缀表达式中缀表达式转为前缀表达式可以使用1.加括号a(b-c)*d -- (a((b-c)*d))2.将运算符移到每对运算式的左边(a(*(-bc)d))3.去括号a*-bcd第7题树假设字母表{a, b, c, d, e}在字符串出现的频率分别为10%15%30%16%29%。若使用哈夫曼编码方式对字母进行不定长的二进制编码字母d的编码长度为 位。A.1B.2C.2或3D.3【答案】B【解析】哈夫曼编码每次就是选择两个最小的频率合成出一个新的数依次往复构成一棵树。此题先用10和15合成25再选16和25合成41再选29和30合成59最后把41和59合成100。构建哈夫曼树后往左走的都是0往右走的都是1d的编码长度为2位编码为00。第8题树一棵有n个结点的完全二叉树用数组进行存储与表示已知根结点存储在数组的第1个位置。若存储在数组第9个位置的结点存在兄弟结点和两个子结点则它的兄弟结点和右子结点的位置分别是 。A.8、18B.10、18C.8、19D.10、19【答案】C【解析】完全二叉树在数组中存放的形式为[1,2,3,4,5,6,7,8,9,…]。9为奇数即右节点其兄弟节点是8其右子节点是n*21即19。第9题图考虑由N个顶点构成的有向连通图采用邻接矩阵的数据结构表示时该矩阵中至少存在 个非零元素。A.N-1B.NC.N1D.N 2 N^2N2【答案】B【解析】可以举一个简单的有向连通图1-2-3-4-1。n个顶点需要n条边连接。构成二维矩阵时行编号依次为1234列编号依次为1234有4个非零元素。第10题栈和队列以下对数据结构的表述不恰当的一项为 。A.图的深度优先遍历算法常使用的数据结构为栈。B.栈的访问原则为后进先出队列的访问原则是先进先出。C.队列常常被用于广度优先搜索算法。D.栈与队列存在本质不同无法用栈实现队列。【答案】D【解析】D可以用两个栈去实现队列的功能第11题线性表以下哪组操作能完成在双向循环链表结点p之后插入结点s的效果其中next域为结点的直接后继prev域为结点的直接前驱) 。A.p-next-prevs; s-prevp; p-nexts; s-nextp-next;B.p-next-prevs; p-nexts; s-prevp; s-nextp-next;C.s-prevp; s-nextp-next; p-nexts; p-next-prevs;D.s-nextp-next; p-next-prevs; s-prevp; p-nexts;【答案】D【解析】先将s节点与p的next节点连接起来即s-next p-next; p-next-prev s。然后再将p与s相连s-prev p; p-next s;所以选择D第12题排序以下排序算法的常见实现中哪个选项的说法是错误的 。A.冒泡排序算法是稳定的B.简单选择排序是稳定的C.简单插入排序是稳定的D.归并排序算法是稳定的【答案】B【解析】排序算法是否稳定就是看相同的元素在排序前和排序后相对位置是否稳定。如两个2排序排序后第1个2必须还是在第2个2前面。简单记忆规则如下1.选择、冒泡、插入排序算法中选择不稳定2.归并、堆排序算法中堆不稳定3.快排、希尔排序算法两个都不稳定4.基数、桶、计数排序算法都稳定第13题数据表示与计算八进制数32.1对应的十进制数是 。A.24.125B.24.250C.26.125D.26.250【答案】C【解析】其他进制转十进制的方法为按权展开求和。3 ∗ 8 1 2 ∗ 8 0 1 ∗ 8 − 1 26.125 3*8^12*8^01*8^{-1}26.1253∗812∗801∗8−126.125第14题组合学一个字符串中任意个连续的字符组成的子序列称为该字符串的子串则字符串abcab有 个内容互不相同的子串。A.12B.13C.14D.15【答案】B【解析】一种方法就是列出所有的子串注意需要包括空串。另一种可以按插空法计算。左端点有6种选择方式右端点有5种选择方式所以共6*530种此时没有考虑右端点小于左端点所以需要30/215种再加上1个空串共16种相同子串中ab有2个a有2个b有2个相同的子串可以只算1个所以需要16-313种选B。第15题计算机语言与算法以下对递归方法的描述中正确的是 A.递归是允许使用多组参数调用函数的编程技术B.递归是通过调用自身来求解问题的编程技术C.递归是面向对象和数据而不是功能和逻辑的编程语言模型D.递归是将用某种高级语言转换为机器代码的编程技术【答案】B【解析】递归就是通过调用自身来解决问题的一种编程技术阅读程序#include iostream using namespace std; int main() { unsigned short x, y; //short占2字节unsigned short范围为0~65535 cin x y; x (x | x 2) 0x33; //x 2 表示转为二进制后左移2位 x (x | x 1) 0x55; //x 1 表示转为二进制后左移1位 y (y | y 2) 0x33; y (y | y 1) 0x55; unsigned short z x | y 1; cout z endl; return 0; }假设输入的x、y均是不超过15的自然数完成下面的判断题和单选题第16题删去第7行与第13行的unsigned程序行为不变。 A.正确B.错误【答案】A【解析】设xabcdyefghx0000abcdx200abcd00x | x200aba|cb|dcd0x3300110011(x | x 2) 0x3300ab00cdx00ab00cdx10ab00cd0x | x10aa|bb0cc|dd0x5501010101(x | x1) 0x550a0b0c0dx0a0b0c0dy0e0f0g0hy1e0f0g0h0x | y1eafbgchdzeafbgchd如果删除unsgined则范围变为-32768 ~ 32767而输入x和y都是不超过15的自然数半个字节左移2位也最多乘41个字节不会超过范围所以不会改变。第17题将第7行与第13行的short均改为char程序行为不变。 A.正确B.错误【答案】B【解析】改为charcin会按照字符读入做位运算会按照ASCII码进行运算程序行为会发生变化。第18题程序总是输出一个整数“0”。 A.正确B.错误【答案】B【解析】可以同19和20题一起做输入2和2输出为12。第19题当输入为“2 2”时输出为“10”。 A.正确B.错误【答案】B【解析】输入2和2x0010y0010abd0c1efh0g1。eafbgchd00001100输出为12。注意优先级关系为左移/右移 按位与 按位或 与或非第20题当输入为“2 2”时输出为“59”。 A.正确B.错误【答案】B【解析】同19题输出为12。第21题当输入为“13 8”时输出为 。A.“0”B.“209”C.“197”D.“226”【答案】B【解析】同19题输入13和8计算输出209#include algorithm #include iostream #include limits using namespace std; const int MAXN 105; const int MAXK 105; int h[MAXN][MAXK]; int f(int n, int m) { if (m 1) return n; if (n 0) return 0; int ret numeric_limitsint::max(); //返回编译器允许的int型数最大值。2^31-12148473647 for (int i1; in; i) ret min(ret, max(f(n-i, m), f(i-1, m-1)) 1); return ret; } int g(int n, int m) //g函数与f函数实现功能一致f函数使用递归实现g函数使用递推实现 { for (int i1; in; i) h[i][1] i; for (int j1; jm; j) h[0][j] 0; for (int i1; in; i) { for (int j2; jm; j) { h[i][j] numeric_limitsint::max(); for (int k 1; ki; k) h[i][j] min( h[i][j], max(h[i-k][j], h[k-1][j-1]) 1); } } return h[n][m]; } int main() { int n, m; cin n m; cout f(n, m) endl g(n, m) endl; return 0; }假设输入的n、m均是不超过100的正整数完成下面的判断题和单选题第22题当输入为“7 3”时第19行用来取最小值的min函数执行了449次。 A.正确B.错误【答案】B【解析】尝试打表理解题意。h[3][2]是求出交叉单元格的极大值之后的极小值n\m1234567000000001111111122222222332222224433333355333333设g[][]记录计算次数n1,m2ret min(ret, max(f[0][2],f[0][1])1) 则g[1][2]1g[0][2]g[0][1]1n\m12300001011n2,m2i1ret min(ret, max(f[1][2],f[0][1])1)i2ret min(ret, max(f[0][2],f[1][1])1)则g[2][3]2g[1][2]g[0][2]g[0][2]g[1][2]3同理g[3][2]7g[3][3]12g[4][2]15g[4][3]32发现n行第2列的g[i][2]2 i 2^i2i-1。最后计算g[4][3]32,g[5][3]80,g[6][3]192,g[7][3]448第23题输出的两行整数总是相同的。 A.正确B.错误【答案】A【解析】f和g函数初值、递归/递推形式完全一致所以结果也相同。第24题当m为1时输出的第一行总为n。 A.正确B.错误【答案】A【解析】第14行m1时return n第25题算法g(n, m)最为准确的时间复杂度分析结果为 。A.O ( n 3 / 2 m ) O(n^{3/2}m)O(n3/2m)B.O ( n m ) O(nm)O(nm)C.O ( n 2 m ) O(n^2m)O(n2m)D.O ( n m 2 ) O(nm^2)O(nm2)【答案】C【解析】i从1到nj从1到mk从1到in ∗ m ∗ n n 2 ∗ m n * m * n n^2 * mn∗m∗nn2∗m第26题当输入为“20 2”时输出的第一行为 。A.“4”B.“5”C.“6”D.“20”【答案】C【解析】画二维矩阵表计算行i表示n列j表示m通过i、j、k代入运算可以发现规律为前i-1行第1列和第2列的数字交叉取最大值取出最大值后再取其中的最小值并将该值加1。列j为2时可以看出规律为1个12个23个34个45个56个6…所以i为20时j为6。n\m120001112223324435536637748849941010411115第27题当输入为“100 100”时输出的第一行为 。A.“6”B.“7”C.“8”D.“9”【答案】B【解析】100楼层扔7次就可以测出最高的扔鸡蛋不碎的楼层。7个鸡蛋就够用。最坏情况下6次不一定测得出来7次一定测得出来。如果用暴力枚举列j为3时可以看出规律为1个12个24个38个416个532个664个7。列j为4时发现规律同列3因为列3和列4数字相同所以即使到列100规律也同列3。所以i为100时j为7种。#include iostream using namespace std; int n, k; int solve1() //返回使得x²≤n的最大整数x { int l 0, r n; while (lr) { int mid (lr)/2; if (mid * mid n) l mid1; else r mid -1; } return l-1; //l-1是满足(l-1)²≤n的最大数 } double solve2(double x) { if (x 0) return x; for (int i0; ik; i) x (x n/x) / 2; //假设x数列有极限A随着k增加xi会越来越接近√n。牛顿迭代法求平方根边长x最后趋向于根号n return x; } int main() { cin n k; double ans solve2(solve1()); cout ans (ans * ans n) endl; return 0; }假设int为32位有符号整数类型输入的n是不超过47000的自然数、k是不超过int表示范围的自然数完成下面的判断题和单选题第28题该算法最准确的时间复杂度分析结果为O(lognk) 。 A.正确B.错误【答案】A【解析】solve1的时间复杂度是lognsolve2的时间复杂度是k第29题当输入为“9801 1”时输出的第一个数为“99”。 A.正确B.错误【答案】A【解析】sovle1的作用就是求n的平方根n9801时n的平方根就是99第30题对于任意输入的n随着所输入k的增大输出的第二个数会变成“1”。 A.正确B.错误【答案】B【解析】如果n不是整数的平方由于舍入误差的原因ans会接近n \sqrt nn但不会等于n \sqrt nn。原因就是double类型在运算过程中会发生截断误差。例如输入“3 10”循环到后面x是不变的第31题该程序有存在缺陷。当输入的n过大时第12行的乘法有可能溢出因此应当将mid强制转换为64位整数再计算。 A.正确B.错误【答案】B【解析】最大值是(47000/2)^2mid (047000)/2 23500不超过int的最大值2147483647第32题当输入为“2 1”时输出的第一个数最接近 。A.1B.1.414C.1.5D.2【答案】C【解析】代入计算得到1.5第33题当输入为“3 10”时输出的第一个数最接近 。A.1.7B.1.732C.1.75D.2【答案】B【解析】代入计算得到3 \sqrt 33。solve2几次循环后就会发现x的数值不再发生改变第34题当输入为“256 11”时输出的第一个数 。A.等于16B.接近但小于16C.接近但大于16D.前三种情况都有可能【答案】A【解析】同29题结果等于16完善程序从小到大打印正整数n的所有正因数。试补全枚举程序。#include bits/stdc.h using namespace std; int main() { int n; cin n; vectorintfac; fac.reserve((int)ceil(sqrt(n))); //为fac申请一片内存空间对程序理解无影响 int i; for (i1; i*in; i) { //此循环是将小于√n的所有因数放入到fac中 if (__1__) { fac.push_back(i); } } for (int k0; kfac.size(); k) { //将fac中已经存放的数据打印出来 cout __2__ ; } if (__3__) { //如果不能理解可以先跳过3、4直接看第5个空。这里用来处理i*in的数 cout __4__ ; } for (int kfac.size()-1; k0; --k) { //逆序枚举fac cout __5__ ; } }第35题1处应填 A.n % i 0B.n % i 1C.n % (i-1) 0D.n % (i-1) 1【答案】A【解析】题目是求n的因数所以此处为n的因数时放到fac中。所以选A第36题2处应填 A.n / fac[k]B.fac[k]C.fac[k]-1D.n / (fac[k]-1)【答案】B【解析】将已经放入fac中的小鱼n \sqrt nn的因数打印出来第37题3处应填 A.(i-1) * (i-1) nB.(i-1) * i nC.i * i nD.i * (i-1) n【答案】C【解析】如果n916行之前输出的内容是124到26行输出的是9还缺个3所以3、4空合起来应该是要能输出3。因为3*39所以倒推出来选C第38题4处应填 A.n-iB.n-i1C.i-1D.i【答案】D【解析】同37题输出这个i即n \sqrt nn第39题5处应填 A.n / fac[k]B.fac[k]C.fac[k]-1D.n / (fac[k]-1)【答案】A【解析】如果n6其正因数有1、2、3、616行之前fac中存放到是1和2而3和6可通过n/fac[k]得到所以选A洪水填充现有用字符标记像素颜色的8x8图像。颜色填充的操作描述如下给定起始像素的位置和待填充的颜色将起始像素和所有可达的像素可达的定义经过一次或多次的向上、下、左、右四个方向移动所能到达且终点和路径上所有像素的颜色都与起始像素颜色相同替换为给定的颜色。试补全程序。#include bits/stdc.h using namespace std; const int ROWS 8; const int COLS 8; struct Point { int r, c; Point(int r, int c): r(r), c(c) {} //构造函数 }; bool is_valid(char image[ROWS][COLS], Point pt, int prev_color, int new_color) { int r pt.r; int c pt.c; return (0r rROWS 0c cCOLS //判断r和c在图像中 __1__ image[r][c] ! new_color); //image[r][c]!new_color表示颜色没有被修改过 } void flood_fill(char image[ROWS][COLS], Point cur, int new_color) { //cur是[4,4]new_color是y queuePoint queue; queue.push(cur); int prev_color image[cur.r][cur.c]; //prev_color b __2__; while (!queue.empty()) { Point pt queue.front(); queue.pop(); Point points[4] {__3__, Point(pt.r - 1, pt.c), Point(pt.r, pt.c 1), Point(pt.r, pt.c -1)}; for (auto p:points) { //基于范围的枚举会从points中的4个位置依次枚举 if (is_valid(image, p, prev_color, new_color)) { __4__; __5__; } } } } int main() { char image[ROWS][COLS] {{g,g,g,g,g,g,g,g}, {g,g,g,g,g,g,r,r}, {g,r,r,g,g,r,g,g}, {g,b,b,b,b,r,g,r}, {g,g,g,b,b,r,g,r}, {g,g,g,b,b,b,b,r}, {g,g,g,g,g,b,g,g}, {g,g,g,g,g,b,b,g}}; Point cur(4, 4); //相当于cur.r4cur.c4 char new_color y; flood_fill(image, cur, new_color); //将[4,4]位置的b及可达的b都换成y for (int r0; rROWS; r) { for (int c0; cCOLS; c) { cout image[r][c] ; } cout endl; } // 输出 // g g g g g g g g // g g g g g g r r // g r r g g r g g // g y y y y r g r // g g g y y r g r // g g g y y y y r // g g g g g y g g // g g g g g y y g return 0; }第40题1处应填 A.image[r][c] prev_colorB.image[r][c] ! prev_colorC.image[r][c] new_colorD.image[r][c] ! new_color【答案】A【解析】该位置上下左右的颜色要与原来的原色相同才可以灌溉。所以选A第41题2处应填 A.image[cur.r1][cur.c] new_colorB.image[cur.r][cur.c] new_colorC.image[cur.r][cur.c1] new_colorD.image[cur.r][cur.c] prev_color【答案】B【解析】上一句是将之前的颜色保存至prev_color中所以此行应该是要把新的颜色赋予当前的位置即[cur.r][cur.c]第42题3处应填 A.Point(pt.r, pt.c)B.Point(pt.r, pt.c1)C.Point(pt.r1, pt.c)D.Point(pt.r1, pt.c1)【答案】C【解析】通过其他三个位置变换可以推测出此行的目的是获得原有坐标的上下左右位置第43题4处应填 A.prev_color image[p.r][p.c]B.new_color image[p.r][p.c]C.image[p.r][p.c] prev_colorD.image[p.r][p.c] new_color【答案】D【解析】如果判断该位置可以灌溉需要把新的颜色赋值给该位置选D第44题5处应填 A.queue.push§B.queue.push(pt)C.queue.push(cur)D.queue.push(Point(ROWS, COLS))【答案】A【解析】需要把新的位置p放入到队列中所以选A