2026年CSP-S初赛模考(6月)
欢迎大家订阅我的专栏:算法题解:C++与Python实现!
本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战!
专栏特色
1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的代码实现与详细指导,帮助您夯实算法基础。
2.系统化学习路径:按照算法类别和难度分级,从基础到进阶,循序渐进,帮助您全面提升编程能力与算法思维。
适合人群:
- 准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生
- 希望系统学习C++/Python编程的初学者
- 想要提升算法与编程能力的编程爱好者
附上汇总贴:历年CSP-J初赛真题解析 | 汇总_热爱编程的通信人的博客-CSDN博客
单选题
第1题
向一个初始为空的小根堆中依次插入:6,2,9,1,5,8,3,然后连续删除 3 次堆顶。此时的堆顶元素是( )。
A. 1
B. 2
C. 3
D. 5
第2题
将 13 个苹果放入 4 个盒子中,在所有放置方式中,苹果个数最多的盒子最少有多少个苹果?( )
A. 3
B. 4
C. 5
D. 6
第3题
设字符串 A="abcbdab",B="bdcaba"。它们的最长公共子序列长度为( )。
A. 3
B. 4
C. 5
D. 6
第4题
在线段树中,根结点表示区间 [1,16],每次将区间从中点均分成左右两半。若查询区间为 [5,13],用最少的线段树结点区间恰好覆盖它,需要多少个结点区间?( )
A. 2
B. 3
C. 4
D. 5
第5题
一个有向图的某个拓扑序为 2,1,4,3,5,下列哪条边不可能出现在该图中?( )
A. \(2\rightarrow 4\)
B. \(1\rightarrow 3\)
C. \(4\rightarrow 5\)
D. \(5\rightarrow 1\)
第6题
以下程序的时间复杂度为?( )
int cnt = 0;
for (int i=n; i>=1; i>>=1)
for (int j=1; j<=i; j++)
++cnt;
A. \(O(n^2)\)
B. \(O(nlogn)\)
C. \(O(n)\)
D. \(O(log^2n)\)
第7题
在一棵以结点 1 为根的树中,已知 LCA(8,12)=4,LCA(12,15)=6。下列说法一定正确的是?( )
A. LCA(8,15) = 4
B. LCA(8,15) = 6
C. LCA(8,15)只可能是4或6
D. LCA(8,15)可能是既不是4也不是6的结点
第8题
将序列 8,3,10,1,6,14,4,7,13 依次插入一棵初始为空的二叉搜索树(较小数放在左子树)。该树的后序遍历结果为( )。
A. 1, 4, 7, 6, 3, 13, 14, 10, 8
B. 1, 3, 4, 6, 7, 8, 10, 13, 14
C. 8, 3, 1, 6, 4, 7, 10, 14, 13
D. 1, 4, 6, 7, 3, 13, 14, 10, 8
第9题
向一棵初始为空的 Trie 树中依次插入 aba,abb,ba,bab,aba,若根结点不计入新增结点数,则每次插入新增结点数依次为( )。
A. 3, 1, 2, 1, 0
B. 3, 2, 2, 1, 0
C. 3, 1, 2, 2, 0
D. 3, 1, 1, 1, 0
第10题
哈希表长度为 7,哈希函数为 h(x)=x mod 7。采用拉链法(链地址法)解决冲突,依次插入 10,21,15,28,8,35,则下标为 1 的链表中有多少个元素?( )
A. 1
B. 2
C. 3
D. 4
第11题
从 1,2,3,…,10 中选出 4 个数,要求任意两个数不相邻,共有多少种选法?( )
A. 56
B. 28
C. 35
D. 70
第12题
有两棵树,直径长度分别为 6 和 8。现在在两棵树之间添加一条边权为 1 的边,将它们连成一棵树。若希望新树直径尽可能小,则新树直径长度最小可能为( )。
A. 8
B. 7
C. 6
D. 9
第13题
设字符串 P="ababc",在字符串匹配过程中,若当前已经匹配了前 4 个字符,即 j=4,但下一个字符失配,则 j 应回退到( )。
A. 0
B. 1
C. 2
D. 3
第14题
一张无向连通图有 5 个点,边及边权如下(前两个数为点编号,后一个数为边权):(1,2,1),(1,3,1),(2,3,1),(2,4,2),(3,4,2),(4,5,3),(3,5,4),该图不同的最小生成树数量为( )。
A. 6
B. 4
C. 3
D. 8
第15题
有 \(6\) 个任务,每个任务耗时均为 \(1\)。第 \(i\) 个任务的截止时间为 \(d_i\),若按时完成可获得收益 \(w_i\)。每个时间单位最多完成一个任务,任务最早可以从时刻 \(1\) 开始执行,并且若任务在时刻 \(d_i\) 或之前完成,则认为按时完成。
各任务的截止时间 \(d_i\) 分别为:2,1,2,3,3,4。
各任务的收益 \(w_i\) 分别为:50,30,60,30,40,70。
其中第 \(i\) 个数对应任务 \(A_i\)。使用解决该类单位时间任务调度问题的贪心算法时,为得到最大的总收益,第一步应如何选择和安排任务?( )
A. 选择 \(w_i/d_i\) 最小的任务 \(A_4\),并将其安排在时刻 \(1\)
B. 选择 \(w_i/d_i\) 最大的任务 \(A_2\),并将其安排在不超过其截止时间的最晚空闲时刻
C. 选择编号最小的任务 \(A_1\),并将其安排在时刻 \(1\)
D. 选择收益最大的任务 \(A_6\),并将其安排在不超过其截止时间的最晚空闲时刻
阅读程序题
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
bool check1(int n, int m, vector<int>& a) {
for (int i=n; i>=1; --i) {
if (m >= a[i]) {
m -= a[i];
}
}
return m == 0;
}
bool check2(int n, int m, vector<int>& a) {
vector<int> f(m + 1);
f[0] = 1;
for (int i=1; i<=n; ++i) {
for (int j=m; j>=a[i]; --j) {
f[j] |= f[j-a[i]];
}
}
return f[m]>0;
}
int n, m;
int main() {
cin >> n >> m;
vector<int> a(n + 1);
for (int i=1; i<=n; ++i) {
a[i] = i;
}
cout << check1(n, m, a) << " " << check2(n, m, a) << "\n";
return 0;
}
假设输入满足 \(1≤n≤100, 0≤m≤10^5\),回答下列问题。
第16题
check1 函数与 check2 函数的返回值始终一致。( )
A. 正确
B. 错误
第17题
将第 31 行的 "a[i] = i;" 改为 "cin >> a[i];",且输入的 "a[i]" 为正整数,那么程序的输出结果有可能会发生改变。( )
A. 正确
B. 错误
第18题
check2 函数基于完全背包的思想。( )
A. 正确
B. 错误
第19题
若输入 "10 56",该程序会输出( )。
A. 1 1
B. 1 0
C. 0 1
D. 0 0
第20题
将第 7 行的循环改为从 1 到 n 枚举后,若输入 "100 4851",该程序会输出( )。
A. 0 1
B. 1 0
C. 1 1
D. 0 0
第21题
做出以下哪种修改,可能会导致程序的输出发生变化?( )
A. 将第 18 行的循环改为从 n 到 1 枚举
B. 将第 17 行改为 "f[0] = 3"
C. 将第 7 行的循环改为从 1 到 n 枚举
D. 将第 9 行的 "m -= a[i]" 改为 "m -= i"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 100005;
int n, q;
int a[MAXN], x[MAXN], ans[MAXN];
void solve(int l, int r, vector<int> query) {
if (query.empty()) return;
if (l==r) {
for (int id : query) {
ans[id] = (a[l] >= x[id] ? l : n + 1);
}
return;
}
int mid = (l + r) / 2;
vector<int> left, right;
for (int id : query) {
if (a[mid] >= x[id]) {
left.push_back(id);
} else {
right.push_back(id);
}
}
solve(l, mid, left);
solve(mid + 1, r, right);
}
int main() {
cin >> n >> q;
for (int i=1; i<=n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
vector<int> query;
for (int i=1; i<=q; i++) {
cin >> x[i];
query.push_back(i);
}
solve(1, n, query);
for (int i=1; i<=q; i++) {
cout << ans[i] << ' ';
}
return 0;
}
假设输入满足 \(1≤n,q≤10^5, 1≤ai≤10^9\),回答下列问题。
第22题
删除第 11 行的 "if (query.empty()) return;",不会对程序的输出结果造成影响。( )
A. 正确
B. 错误
第23题
第 49 行输出 "ans[i]" 的值可能为 0。( )
A. 正确
B. 错误
第24题
第 30 行到第 31 行的作用是,分别对数组 a 的 "[l, mid]" 和 "[mid + 1, r]" 区间进行排序。( )
A. 正确
B. 错误
第25题
该程序的时间复杂度为( )。
A. \(O(q\sqrt n)\)
B. \(O(nqlogn)\)
C. \(O(nq)\)
D. \(O((n+q)logn)\)
第26题
当输入为 "5 4 7 1 3 9 3 3 4 10 8",程序的输出结果为( )。
A. 1 3 5 4
B. 3 3 5 4
C. 4 4 6 5
D. 2 4 6 5
第27题
当输入为 "6 6 6 2 4 10 8 12 1 4 6 7 12 9",做出如下哪个修改,可以让程序输出 "1 3 4 4 7 5"?( )
A. 删去第 39 行的 "sort(a + 1, a + n + 1);"
B. 将第 49 行的 "ans[i]" 改为 "ans[i] + 1"
C. 将第 23 行的判断条件改为 "a[mid] - 1 >= x[id]"
D. 将第 13 行的判断条件改为 "l <= r"
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int N = 1005, A = 30;
int t[N * N * A][2], mx[N * N * A], cnt;
void Update(int num, int id) {
int cur = 0;
for (int i = A-1; i>=0; --i) {
int e = (num >> i) & 1;
if (t[cur][e] == 0) {
t[cur][e] = ++cnt;
}
cur = t[cur][e];
mx[cur] = max(mx[cur], id);
}
}
int getId(int num) {
int cur = 0, res = 0;
for (int i = A - 1; i>=0; --i) {
int e = (num >> i) & 1;
if (e == 1) {
res = max(res, mx[t[cur][0]]);
}
if (t[cur][e] == 0) {
return res;
}
cur = t[cur][e];
}
return res;
}
int n, s[N][N];
int main() {
cin >> n;
vector<int> a(n + 1);
for (int i=1; i<=n; ++i) {
cin >> a[i];
}
vector<int> mxid(n + 1, 0);
for (int i=1; i<=n; ++i) {
s[mxid[i]][i]++;
for (int j = i+1; j<=n; ++j) {
int pos = getId(a[i] ^ a[j]);
mxid[j] = max(mxid[j], pos);
}
for (int j=1; j<i; ++j) {
Update(a[i] ^ a[j], j);
}
}
int count = 0;
for (int i=n; i>=1; --i) {
for (int j=1; j<=n; ++j) {
s[i][j] += s[i+1][j] + s[i][j-1] - s[i+1][j-1];
if (i<=j && s[i][j]>0)
++count;
}
}
cout << count << "\n";
return 0;
}
假设输入满足 \(1≤n≤10^3, 0≤ai<2^{30}\),回答下列问题。
第28题
将第 55 行的外层循环改为从 1 到 n 枚举后,程序的输出结果不会发生改变。( )
A. 正确
B. 错误
第29题
第 22 行 "(num >> i) & 1" 的作用是计算 "num" 在二进制表示中第 i 位的值。( )
A. 正确
B. 错误
第30题
第 50 行的作用是,将异或值为 "a[i] ^ a[j]" 的历史数对插入 Trie,并在 Trie 结点中维护这些数对较小下标 "j" 的最大值。( )
A. 正确
B. 错误
第31题
将第 31 行改为 return max(res, mx[t[cur][0]]);,程序的输出结果会发生什么变化?( )
A. 无法确定
B. 一定不变
C. 不变或者变小
D. 不变或者变大
第32题
当输入为 "5 1 6 14 4 9",程序的输出结果为( )。
A. 9
B. 10
C. 3
D. 4
第33题
记区间 [L,R] 满足 1≤L≤R≤n,再记 ⊕ 表示按位异或运算,则该程序所求的是( )。
A. 四元组的个数,满足 \(a_p\oplus a_q\le a_i \oplus a_j\) 且 \(L\le p \lt q\lt i\lt j\le R\)。
B. 区间 \([L, R]\) 的个数,满足 \(a_p\oplus a_q\ge a_i \oplus a_j\) 且 \(L\le p \lt q\lt i\lt j\le R\)。
C. 四元组的个数,满足 \(a_p\oplus a_q\gt a_i \oplus a_j\) 且 \(L\le p \lt q\lt i\lt j\le R\)。
D. 区间 \([L, R]\) 的个数,满足 \(a_p\oplus a_q\lt a_i \oplus a_j\) 且 \(L\le p \lt q\lt i\lt j\le R\)。
完善程序题
给定一张 \(n (1≤n≤10^5)\) 个点、\(m (n−1≤m≤10^5)\) 条边的无向连通带权图,所有边权均为正整数。图中有 \(k (2≤k≤n)\) 个互不相同的特殊点。请在这些特殊点中选出两个不同的点,使得它们之间的最短路长度最小,并输出这个最小值。
以所有特殊点为起点做最短路,在计算过程中不断更新不同特殊点之间的距离。请补全程序中的空缺。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
struct Edge {
int to, w;
};
vector<Edge> e[N];
int n, m, k, id[N], vis[N];
long long dis[N];
int main() {
cin >> n >> m;
for (int i=1; i<=m; ++i) {
int u, v, w;
cin >> u >> v >> w;
e[u].push_back({v, w});
e[v].push_back({u, w});
}
memset(dis, __1__, sizeof(dis));
priority_queue<pair<long long, int>> q;
cin >> k;
for (int i=1; i<=k; ++i) {
cin >> x;
q.push({0, x});
dis[x] = 0;
__2__;
}
long long ans = 1e18;
while (q.size()) {
int u = q.top().second;
q.pop();
if (vis[u]==1) continue;
vis[u] = 1;
for (auto p : e[u]) {
int v = p.to, w = p.w;
if (id[u] != id[v]) {
ans = min(ans, __3__);
}
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
__4__;
q.push(__5__);
}
}
}
cout << ans << "\n";
return 0;
}
第34题
1处应填( )。
A. 0
B. -1
C. -0x3f
D. 0x3f
第35题
2处应填( )。
A. vis[x] = x
B. id[x] = x
C. vis[x] = 1
D. id[x] = 1
第36题
3处应填( )。
A. dis[id[u]] + dis[id[v]]
B. dis[u] + dis[v]
C. min(dis[v], dis[u] + w)
D. dis[u] + dis[v] + w
第37题
4处应填( )。
A. id[v] = u
B. id[v] = (id[v] == 0) ? u : id[v]
C. id[v] = id[u]
D. id[v] = (id[v] == 0) ? id[u] : id[v]
第38题
5处应填( )。
A. -dis[v], v
B. dis[v], v
C. dis[u] + w, v
D. -dis[v], id[v]
请补全程序中的空缺。
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
#define ll long long
const int P = 1e9 + 7;
int qpow(int a, int b, int p) {
int res = 1;
while (b>0) {
if (b&1)
res = (ll)res * a % p;
a = (ll)a * a % p;
b >>= 1;
}
return res;
}
void add(int& x, int y) {
x += y;
x %= P;
}
int mul(int x, int y) {
return (ll)x * y % P;
}
struct Node {
int l, r, w;
};
int main() {
int n, m, k;
cin >> n >> m >> k;
map<int, int> id;
for (int i=1, x, y; i<=k; ++i) {
cin >> x >> y;
id[y] = x;
}
int prey = 0, sum = 1;
vector<Node> lst = {{1, 1, 1}, {2, n, 0}};
for (auto p : id) {
int y = p.first, x = p.second;
vector<Node> cur = {__1__};
if (prey != y - 1) {
int len = y - prey - 1;
lst.clear();
lst.push_back({1, n, mul(sum, qpow(n, __2__, P))});
}
for (int i=0; i<cur.size(); ++i) {
int tot = 0, tmp;
for (int j=0; j<lst.size(); ++j) {
__3__;
tmp = mul(max(R - L + 1, 0), lst[j].w);
add(tot, tmp);
}
if (cur[i].w == -1) {
cur[i].w = 0;
} else {
cur[i].w = __4__;
}
}
prey = y, sum = 0;
lst = cur;
for (auto it : lst) {
add(sum, mul(it.r - it.l + 1, it.w));
}
}
cout << (prey != m ? mul(sum, qpow(n, m - prey - 1, P)) : __5__) << "\n";
return 0;
}
第39题
1处应填( )。
A. {1, x - 1, 0}, {x, x, -1}, {x + 1, n, 0}
B. {1, x, 1}, {x, x, -1}, {x, n, 1}
C. {1, x - 1, 0}, {x, x, 1}, {x + 1, n, 0}
D. {1, x - 1, -1}, {x, x, 0}, {x + 1, n, -1}
第40题
2处应填( )。
A. len
B. len + 1
C. len - 1
D. 1
第41题
3处应填( )。
A. int L = min(lst[j].l, cur[i].l), R = max(lst[j].r, cur[i].r)
B. int L = max(lst[j].l, cur[i].l), R = min(lst[j].r, cur[i].r)
C. int L = max(lst[j].l, cur[i].r), R = min(lst[j].r, cur[i].l)
D. int L = max(lst[j].r, cur[i].l), R = min(lst[j].l, cur[i].r)
第42题
4处应填( )。
A. tot + 1
B. tot + n
C. tot
D. tot * n
第43题
5处应填( )。
A. sum * n
B. sum
C. (lst.back().r - lst.back().l) * lst.back().w
D. lst.back().w
浙公网安备 33010602011771号