正在载入在线练习界面,本页内容可直接阅读…
AK CSP › CSP-S 2025 第一轮真题 › 第26题
CSP-S 2025 第一轮 第26题:程序阅读第 2 题 · 第 5 小题
题目
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
int cnt_broken = 0;
int cnt_check = 0;
int n, k;
inline bool check(int h) {
printf("now check:%d\n", h);
++cnt_check;
if (cnt_broken == 2) {
printf("You have no egg!\n");
return false;
}
if (h >= k) {
++cnt_broken;
return true;
} else {
return false;
}
}
inline bool assert_ans(int h) {
if (h == k) {
printf("You are Right using %d checks\n", cnt_check);
return true;
} else {
printf("Wrong answer!\n");
return false;
}
}
inline void guess1(int n) {
for (int i = 1; i <= n; ++i) {
if (check(i)) {
assert_ans(i);
return;
}
}
}
inline void guess2(int n) {
int w = 0;
for (w = 1; w * (w + 1) / 2 < n; ++w)
;
for (int ti = w, nh = w;; --ti, nh += ti, nh = std::min(nh, n)) {
if (check(nh)) {
for (int j = nh - ti + 1; j < nh; ++j) {
if (check(j)) {
assert_ans(j);
return;
}
}
assert_ans(nh);
return;
}
}
}
int main() {
scanf("%d%d", &n, &k);
int t;
scanf("%d", &t);
if (t == 1) {
guess1(n);
} else {
guess2(n);
}
return 0;
}
注意:下述的“猜测数”为调用 check 函数的次数(即 $cnt\_check$ 的值);“猜测正确”的含义为 assert_ans 函数 return true(执行第 25 行所在分支)的情况;所有输入保证 $1 \leq k \leq n$)。本小题
函数 guess2 在运行过程中,最多使用的猜测次数的量级为( )。
选项
- A. $O(n)$
- B. $O(n^2)$
- C. $O(\sqrt{n})$
- D. $O(\log n)$
答案
C
题解
选 C. \(O(\sqrt n)\)。
关键是:guess2 先跳着检查,遇到鸡蛋摔碎,再逐层检查。
首先,程序找到最小的 \(w\),使得 \[ 1+2+\cdots+w=\frac{w(w+1)}2\ge n, \] 所以 \(w=\Theta(\sqrt n)\)。
随后,检查的楼层依次是 \[ w,\quad w+(w-1),\quad w+(w-1)+(w-2),\quad\ldots \] 每次跳跃的步长减小 \(1\),超过 \(n\) 时取 \(n\)。
假设第 \(r\) 次跳跃检查时鸡蛋摔碎:
- 此时
ti = w-r+1; - 内层循环从
nh-ti+1检查到nh-1,最多调用check\(ti-1=w-r\) 次; - 加上前面的 \(r\) 次,总共最多
\[ r+(w-r)=w \] 次。
因此,最多猜测次数的量级为 \(O(\sqrt n)\)。
注意:虽然有两层循环,但内层循环只在鸡蛋摔碎后执行一次,随后函数就返回,不能直接把两层循环的次数相乘。
真题版权归 CCF 所有,本站仅用于非商业教学用途。页面加载后可直接在线作答,作答记录保存在本浏览器或账号中。 京ICP备2026056990号-1
京公网安备11010502062986号