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

posted @ 2026-06-20 15:03  团爸讲算法  阅读(35)  评论(1)    收藏  举报