2024CCF 提高级 CSP-S 初赛
2024CCF 提高级 CSP-S 初赛
- 分類:CSP-S 提高组
- 來源:https://lib.nbdp.net/paper/146.html
2024CCF 提高级 CSP-S 初赛
一、单选题(每题 2 分,共 30 分) 查看答案
第 1 题 在Linux 系统中,如果你想显示当前工作目录的路径,应该使用哪个命令?( )
- A. pwd
- B. cd
- C. Ls
- D. echo
答案: A. pwd
第 2 题 假设一个长度为n 的整数数组中每个元素互不相同,且这个数组是无序的。要找到这个 数组中最大元素的时间复杂度是多少?( )
- A. O(n)
- B. O(log n)
- C. O(n log n)
- D. O(1)
答案: A. O(n)
第 3 题 在C++中,以下哪个函数调用会造成栈溢出?( )
- A. int foo( return 0; )
- B. Int bar( int x=1; return x)
- C. Void baz() { int a[1000];baz();}
- D. Void qux() {return;}
答案: C. Void baz() { int a[1000];baz();}
第 4 题 在一场比赛中,有10 名选手参加,前三名将获得金银铜牌,若不允许并列,且每名选手 只能获得一枚铜牌,则不同的颁奖方式共有多少种?( )
- A. 120
- B. 720
- C. 504
- D. 1000
答案: B. 720
第 5 题 下面那个数据结构最适合实现先进先出(FIFO)的功能?( )
- A. 栈
- B. 队列
- C. 线性表
- D. 二叉搜索树
答案: B. 队列
第 6 题 一直f(1) = 1,且对于n>=2 有f(n) = f(n -1) + f( n/2 ) ,则f(4)的值为:( )
- A. 4
- B. 5
- C. 6
- D. 7
答案: B. 5
第 7 题 假设一个包含n 个顶点的无向图,且该图是欧拉图。一下关于该图的描述中哪一项不一 定正确?( )
- A. 所有顶点的度数均为偶数
- B. 该图联通
- C. 该图存在一个欧拉回路
- D. 该图的边数是奇数
答案: D. 该图的边数是奇数
第 8 题 对数组进行二分查找的过程中,以下哪个条件必须满足?( )
- A. 数组必须是有序的
- B. 数组必须是无序的
- C. 数组长度必须是2 的幂
- D. 数组中的元素必须是整数
答案: A. 数组必须是有序的
第 9 题 考虑一个自然数n 以及一个模数m,你需要计算n 的逆元(即n 在模m 意义下的乘法逆 元)。下列哪种算法最为合适?( )
- A. 使用暴力方法依次尝试
- B. 使用扩展欧几里得解法
- C. 使用快速幂解法
- D. 使用线性筛法
答案: B. 使用扩展欧几里得解法
第 10 题 在设计一个哈希表时,为了减少冲突,需要使用适当的哈希函数和和冲突解决策略。已 知某哈希表中有n 个键值对,表的装载因子为α(0<α≤1)。在使用开放地址法解决冲突的 过程中,最坏情况下查找一个元素的时间复杂度为( )
- A. O(1)
- B. O(log n)
- C. O (1/(1-α))
- D. O(n)
答案: D. O(n)
第 11 题 假设有一颗h 层的完全二叉树,该树最多包含多少个节点( )
答案: 1
A.
答案: 1
B.
答案: 1
C.
答案: 1
D.
第 12 题 设有一个10 个顶点的完全图,每两个顶点之间都有一条边,有多少个长度为4 的环? ( )
- A. 120
- B. 210
- C. 630
- D. 5040
答案: C. 630
第 13 题 对于一个整数n,定义f(n)为n 的各个位数之和,问使f(f(x))=10 的最小自然数x 是多少?
- A. 29
- B. 199
- C. 299
- D. 399
答案: B. 199
第 14 题 设有一个长度为n 的01 字符串,其中有k 个1,每次操作可以交换相邻两个字符。在最 坏的情况下将这k 个1 移到字符串最右边所需要的交换次数是多少?( )
- A. K
- B. K*(k-1)/2
- C. (n-k)*k
- D. (2n-k-1)*k/2
答案: C. (n-k)*k
第 15 题 如图是一张包含7 个顶点的有向图。如果要删除一些边,使得从节点1 到节点7 没有可行路径,且删除的边数最少,请问总共有多少种可行的删除边的集合?( )
- A. 1
- B. 2
- C. 3
- D. 4
答案: D. 4
二、判断题(每题 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 时,输出的序列是有序的( )
- A.正确
- B.错误
答案: A.正确
第 17 题 当输入“5 5 1”时,输出为“1 1 5 5 5”( )
- A.正确
- B.错误
答案: 2
第 18 题 假设数组c 长度无限制,该程序所实现的算法的时间复杂度是O(b)的( )
- A.正确
- B.错误
答案: 2
第 19 题 函数int logic(int x,int y)的功能是( )
- A. 按位与
- B. 按位或
- C. 按位异或
- D. 以上都不是
答案: B. 按位或
第 20 题 (4 分)当输入为“10 100 100”时,输出的第100 个数是( )
- A. 91
- B. 94
- C. 95
- D. 98
答案: C. 95
第 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)。 ( )
- A.正确
- B.错误
答案: A.正确
第 23 题 输入“11 2 10000000001”时,程序输出两个数32 和23.( )
- A.正确
- B.错误
答案: A.正确
第 24 题 (2 分)在n≤10 时,solve()的返回值始终小于410( )
- A.正确
- B.错误
答案: 2
第 25 题 当n=10 且m=10 时,有多少种输入使得两行的结果完全一致?()
- A. 1024
- B. 11
- C. 10
- D. 0
答案: C. 10
第 26 题 当n≤5 时,solve()的最大可能返回值为?( )
- A. 65
- B. 211
- C. 665
- D. 2059
答案: C. 665
第 27 题 若n=8,m=8,solve 和solve2 的返回值的最大可能的差值为( )
- A. 1477
- B. 1995
- C. 2059
- D. 2187
答案: C. 2059
第 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)。( )
- A.正确
- B.错误
答案: A.正确
第 30 题 时间开销的瓶颈是init()函数( )
- A.正确
- B.错误
答案: 2
第 31 题 若修改常数B1 或K1 的值,该程序可能会输出不同呢的结果( )
- A.正确
- B.错误
答案: A.正确
第 32 题 在solve()函数种,h[]的合并顺序可以看作是:( )
- A. 二叉树的BFS 序
- B. 二叉树的先序遍历
- C. 二叉树的中序遍历
- D. 二叉树的后序遍历
答案: B. 二叉树的先序遍历
第 33 题 输入“10”,输出的第一行是?( )
- A. 83
- B. 424
- C. 54
- D. 110101000
答案: A. 83
第 34 题 (4 分)输入“16”,输出的第二行是?( )
- A. 7
- B. 9
- C. 10
- D. 12
答案: C. 10
三、编程题(每题 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 题 ⑴处应填( )。
- A. an-a
- B. an-a-1
- C. ai
- D. ai+1
答案: A. an-a
第 37 题 ⑵处应填( )。
答案: 1
ai" lay-filter="filter">
答案: 1
= ai" lay-filter="filter">
- C. a[mid] < ai
- D. a[mid] ≤ ai
答案: 1
第 38 题 ⑶处应填( )。
- A. a+l
- B. a+l+1
- C. a+l-1
- D. an-l
答案: A. a+l
第 39 题 ⑷处应填( )。
- A. a[n-1]+b[n-1]
- B. a[n]+b[n]
- C. 2*maxn
- D. maxn
答案: A. a[n-1]+b[n-1]
第 40 题 ⑸处应填( )。
- A. get_rank(mid) < k
- B. get_rank(mid) ≤ k
答案: A. get_rank(mid) < k
k" lay-filter="filter">
答案: 1
= k" lay-filter="filter">
第 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 题 ⑴处应填( )。
- A. udp(pre[b],n+b,dis[b],q)
- B. upd(a,n+b,d,q)
- C. upd(pre[b],b,dis[b],q)
- D. upd(a,b,d,q)
答案: A. udp(pre[b],n+b,dis[b],q)
第 43 题 ⑵处应填( )。
- A. make_pair(-d,b)
- B. make_pair(d,b)
- C. make_pair(b,d)
- D. make_pair(-b,d)
答案: A. make_pair(-d,b)
第 44 题 ⑶处应填( )。
- A. 0xff
- B. 0x1f
- C. 0x3f
- D. 0x7f
答案: B. 0x1f
第 45 题 ⑷处应填( )。
- A. upd(a,n+b,dis[a]+c,q)
- B. upd(n+a,n+b,dis2[a]+c.q)
- C. upd(n+a,b,dis2[a]+c,q)
- D. upd(a,b,dis[a]+c,q)
答案: A. upd(a,n+b,dis[a]+c,q)
第 46 题 ⑸处应填( )。
- A. pre2[a%n]
- B. pre[a%n]
- C. pre2[a]
- D. pre[a%n]+1
答案: A. pre2[a%n]