2024CCF 提高级 CSP-S 初赛

一、单选题(每题 2 分,共 30 分)
第 1 题 在Linux 系统中,如果你想显示当前工作目录的路径,应该使用哪个命令?( )
第 2 题 假设一个长度为n 的整数数组中每个元素互不相同,且这个数组是无序的。要找到这个 数组中最大元素的时间复杂度是多少?( )
第 3 题 在C++中,以下哪个函数调用会造成栈溢出?( )
第 4 题 在一场比赛中,有10 名选手参加,前三名将获得金银铜牌,若不允许并列,且每名选手 只能获得一枚铜牌,则不同的颁奖方式共有多少种?( )
第 5 题 下面那个数据结构最适合实现先进先出(FIFO)的功能?( )
第 6 题 一直f(1) = 1,且对于n>=2 有f(n) = f(n -1) + f( n/2 ) ,则f(4)的值为:( )
第 7 题 假设一个包含n 个顶点的无向图,且该图是欧拉图。一下关于该图的描述中哪一项不一 定正确?( )
第 8 题 对数组进行二分查找的过程中,以下哪个条件必须满足?( )
第 9 题 考虑一个自然数n 以及一个模数m,你需要计算n 的逆元(即n 在模m 意义下的乘法逆 元)。下列哪种算法最为合适?( )
第 10 题 在设计一个哈希表时,为了减少冲突,需要使用适当的哈希函数和和冲突解决策略。已 知某哈希表中有n 个键值对,表的装载因子为α(0<α<=1)。在使用开放地址法解决冲突的 过程中,最坏情况下查找一个元素的时间复杂度为( )
第 11 题 假设有一颗h 层的完全二叉树,该树最多包含多少个节点( )
A. $2^h-1$
B. $2^{h+1}-1$
C. $2^h$
D. $2^{h+1}$
第 12 题 设有一个10 个顶点的完全图,每两个顶点之间都有一条边,有多少个长度为4 的环? ( )
第 13 题 对于一个整数n,定义f(n)为n 的各个位数之和,问使f(f(x))=10 的最小自然数x 是多少?
第 14 题 设有一个长度为n 的01 字符串,其中有k 个1,每次操作可以交换相邻两个字符。在最 坏的情况下将这k 个1 移到字符串最右边所需要的交换次数是多少?( )
第 15 题 如图是一张包含7 个顶点的有向图。如果要删除一些边,使得从节点1 到节点7 没有可行路径,且删除的边数最少,请问总共有多少种可行的删除边的集合?( )
二、判断题(每题 2 分,共 20 分)
第 16 题
#include <iostream>
using namespace std;

const int N = 1000;
int c[N];

int logic(int x, int y) {
	return (x & y) ^ ((x ^ y) | (~x & y));
}
void generate(int a, int b, int *c) {
	for (int i = 0; i < b; i++) {
		c[i] = logic(a, i) % (b + 1);
	}
}
void recursion(int depth, int *arr, int size) {
	if (depth <= 0 || size <= 1)return;
	int pivot = arr[0];
	int i = 0, j = size - 1;
	while (i <= j) {
		while (arr[i] < pivot)i++;
		while (arr[j] > pivot)j--;
		if (i <= j) {
			int temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
			i++;j--;
		}
	}
	recursion(depth - 1, arr, j + 1);
	recursion(depth - 1, arr + i, size - i);
}

int main() {
	int a, b, d;
	cin >> a >> b >> d;
	generate(a, b, c);
	recursion(d, c, b);
	for (int i = 0; i < b; i++)cout << c[i] << " ";
}
判断题
第 16 题 当1000>=d>=b 时,输出的序列是有序的( )
第 17 题 当输入“5 5 1”时,输出为“1 1 5 5 5”( )
第 18 题 假设数组c 长度无限制,该程序所实现的算法的时间复杂度是O(b)的( )
第 19 题 函数int logic(int x,int y)的功能是( )
第 20 题 (4 分)当输入为“10 100 100”时,输出的第100 个数是( )
第 22 题
#include <iostream>
#include <string>
using namespace std;

const int P = 998244353, N = 1e4 + 10, M = 20;
int n, m;
string s;
int dp[1 << M];

int solve() {
	dp[0] = 1;
	for (int i = 0; i < n; i++) {
		for (int j = (1 << (m - 1)) - 1; j >= 0; j--) {
			int k = (j << 1) | (s[i] - '0');
			if (j != 0 || s[i] == '1')
				dp[k] = (dp[k] + dp[j]) % P;
		}
	}
	int ans = 0;
	for (int i = 0; i < (1 << m); i++) {
		ans = (ans + 1ll * i * dp[i]) % P;
	}
	return ans;
}
int solve2() {
	int ans = 0;
	for (int i = 0; i < (1 << n); i++) {
		int cnt = 0;
		int num = 0;
		for (int j = 0; j < n; j++) {
			if (i & (1 << j)) {
				num = num * 2 + (s[j] - '0');
				cnt++;
			}
		}
		if (cnt <= m)(ans += num) %= P;
	}
	return ans;
}

int main() {
	cin >> n >> m;
	cin >> s;
	if (n <= 20) {
		cout << solve2() << endl;
	}
	cout << solve() << endl;
	return 0;
}
假设输入的 s 是包含 n 个 01 字符串,完成以下的判断题和单选题:
判断题
第 22 题 假设输入的s 是包含n 个字符的01 串,函数solve()所实现的算法时间复杂度是O(n*2^m)。 ( )
第 23 题 输入“11 2 10000000001”时,程序输出两个数32 和23.( )
第 24 题 (2 分)在n<=10 时,solve()的返回值始终小于410( )
第 25 题 当n=10 且m=10 时,有多少种输入使得两行的结果完全一致?()
第 26 题 当n<=5 时,solve()的最大可能返回值为?( )
第 27 题 若n=8,m=8,solve 和solve2 的返回值的最大可能的差值为( )
第 29 题
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1000000 + 5;
const int P1 = 998244353, P2 = 1000000007;
const int B1 = 2, B2 = 31;
const int K1 = 0, K2 = 13;

typedef long long ll;

int n;
bool p[maxn];
int p1[maxn], p2[maxn];

struct H {
	int h1, h2, l;
	H(bool b = false) {
		h1 = b + K1;
		h2 = b + K2;
		l = 1;
	}
	H operator + (const H &h)const {
		H hh;
		hh.l = l + h.l;
		hh.h1 = (1ll * h1 * p1[h.l] + h.h1) % P1;
		hh.h2 = (1ll * h2 * p2[h.l] + h.h2) % P2;
		return hh;
	}
	bool operator == (const H &h)const {
		return l == h.l && h1 == h.h1 && h2 == h.h2;
	}
	bool operator < (const H &h)const {
		if (l != h.l)return l < h.l;
		else if (h1 != h.h1)return h1 < h.h1;
		elsereturn h2 < h.h2;
	}
} h[maxn];

void init() {
	memset(p, 1, sizeof(p));
	p[0] = p[1] = false;
	p1[0] = p2[0] = 1;
	for (int i = 1; i <= n; i++) {
		p1[i] = (1ll * B1 * p1[i - 1]) % P1;
		p2[i] = (1ll * B2 * p2[i - 1]) % P2;
		if (!p[i])continue;
		for (int j = 2 * i; j <= n; j += i) {
			p[j] = false;
		}
	}
}

int solve() {
	for (int i = n; i; i--) {
		h[i] = H(p[i]);
		if (2 * i + 1 <= n) {
			h[i] = h[2 * i] + h[i] + h[2 * i + 1];
		} else if (2 * i <= n) {
			h[i] = h[2 * i] + h[i];
		}
	}
	cout << h[1].h1 << endl;
	sort(h + 1, h + n + 1);
	int m = unique(h + 1, h + n + 1) - (h + 1);
	return m;
}

int main() {
	cin >> n;
	init();
	cout << solve() << endl;
}
判断题
第 29 题 假设程序运行前能自动将maxn 改为n+1,所实现的算法的时间复杂度是O(nlogn)。( )
第 30 题 时间开销的瓶颈是init()函数( )
第 31 题 若修改常数B1 或K1 的值,该程序可能会输出不同呢的结果( )
第 32 题 在solve()函数种,h[]的合并顺序可以看作是:( )
第 33 题 输入“10”,输出的第一行是?( )
第 34 题 (4 分)输入“16”,输出的第二行是?( )
三、编程题(每题 25 分,共 50 分)
第 36 题 (1)合并序列,有两个长度为N 的单调不降序列A 和B,序列的每个元素都是小于10^9 的非负整数。在A 和B 中各取一个数相加可以得到N^2 个和,求其中第k 小的和。上述参 数满足N<=10^5 和1<=K<=N^2
#include <iostream>
using namespace std;

const int maxn = 100005;
int n;
long long k;
int a[maxn], b[maxn];

int *upper_bound(int *a, int *an, int ai) {
	int l = 0, r = __(1)__ ;
	while (l < r) {
		int mid = (l + r) >> 1;
		if ( __(2)__ ) {
			r = mid;
		} else {
			l = mid + 1;
		}
	}
	return __(3)__;
}

long long get_rank(int sum) {
	long long rank = 0;
	for (int i = 0; i < n; i++) {
		rank += upper_bound(b, b + n, sum - a[i]) - b;
	}
	return rank;
}
int solve() {
	int l = 0, r = __(4)__ ;
	while (l < r) {
		int mid = ((long long)l + r) >> 1;
		if ( __(5)__ ) {
			l = mid + 1;
		} else {
			r = mid;
		}
	}
	return l;
}

int main() {
	cin >> n >> k;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	for (int i = 0; i < n; i++)
		cin >> b[i];
	cout << solve() << endl;
	return 0;
}
第 36 题 ⑴处应填( )。
第 37 题 ⑵处应填( )。
第 38 题 ⑶处应填( )。
第 39 题 ⑷处应填( )。
第 40 题 ⑸处应填( )。
第 42 题 (次短路)已知有一个n 个点m 条边的有向图G,并且给定图中的两个点s 和t,求次 短路(长度严格大于最短路的最短路径)。如果不存在,输出一行“-1”。如果存在,输出两 行,第一行表示此段路经的长度,第二行表示此段路的一个方案
#include <cstdio>
#include <queue>
#include <utility>
#include <cstring>
using namespace std;
const int maxn = 2e5 + 10, maxm = 1e6 + 10, inf = 522133279;
int n, m, s, t;
int head[maxn], nxt[maxm], to[maxm], w[maxm], tot = 1;
int dis[maxn << 1], *dis2;
int pre[maxn << 1], *pre2;
bool vis[maxn << 1];
void add(int a, int b, int c) {
	++tot;
	nxt[tot] = head[a];
	to[tot] = b;
	w[tot] = c;
	head[a] = tot;
}
bool upd(int a, int b, int d, priority_queue<pair<int, int> > &q) {
	if (d >= dis[b])return false;
	if (b < n) __(1)__ ;
	q.push( __(2)__ );
	dis[b] = d;
	pre[b] = a;
	return true;
}
void solve() {
	priority_queue<pair<int, int> >q;
	q.push(make_pair(0, s));
	memset(dis, __(3)__ , sizeof(dis));
	memset(pre, -1, sizeof(pre));
	dis2 = dis + n;
	pre2 = pre + n;
	dis[s] = 0;
	while (!q.empty()) {
		int aa = q.top().second;
		q.pop();
		if (vis[aa])continue;
		vis[aa] = true;
		int a = aa % n;
		for (int e = head[a]; e; e = nxt[e]) {
			int b = to[e], c = w[e];
			if (aa < n) {
				if (!upd(a, b, dis[a] + c, q))
					__(4)__
				} else {
				upd(n + a, n + b, dis2[a] + c, q);
			}
		}
	}
}
void out(int a) {
	if (a != s) {
		if (a < n)
			out(pre[a]);
		else
			out( __(5)__ );
	}
	printf("%d%c", a % n + 1, " \n"[a == n + t]);
}
int main() {
	scanf("%d%d%d%d", &n, &m,&s,&t);
	s--, t--;
	for (int i = 0; i < m; i++) {
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		add(a - 1, b - 1, c);
	}
	solve();
	if (dis2[t] == inf)
		puts("-1");
	else {
		printf("%d\n", dis2[t]);
		out(n + t);
	}
	return 0;
}
第 42 题 ⑴处应填( )。
第 43 题 ⑵处应填( )。
第 44 题 ⑶处应填( )。
第 45 题 ⑷处应填( )。
第 46 题 ⑸处应填( )。