正在载入在线练习界面,本页内容可直接阅读…

AK CSP › CSP-J 2025 第一轮真题 › 第 38 题

CSP-J 2025 第一轮 第 38 题:精明与糊涂:①处应填

完善程序 · 贪心算法 · 难度 较难 · 答案 B

题目

(2)(精明与糊涂)有 $N$ 个人,分为两类:
i) 精明人:永远能正确判断其他人是精明还是糊涂;
ii)糊涂人:判断不可靠,会给出随机的判断。

已知精明人严格占据多数,即如果精明人有 $k$ 个,则满足 $k > N/2$。

你只能通过函数 $\text{query}(i, j)$ 让第 $i$ 个人判断第 $j$ 个人:返回 $\text{true}$ 表示判断结果为“精明人”;返回 $\text{false}$ 表示判断结果为“糊涂人”。你的目标是,通过这些互相判断,找出至少一个百分之百确定的精明人。同时,你无需关心 $\text{query}(i, j)$ 的内部实现。

以下程序利用“精明人占多数”的优势。设想一个“消除”的过程,让人们互相判断并进行抵消。经过若干轮抵消后,最终留下的候选人必然属于多数派,即精明人。

例如,假设有三人 $0, 1, 2$。如果 $0$ 说 $1$ 是糊涂人,而 $1$ 也说 $0$ 是糊涂人,则 $0$ 和 $1$ 至少有一个是糊涂人。程序将同时淘汰 $0$ 和 $1$。由于三人里至少有两个精明人,我们确定 $2$ 是精明人。

试补全程序。

#include <iostream>
#include <vector>
using namespace std;

int N;
bool query(int i, int j);

int main() {
    cin >> N;

    int candidate = 0;
    int count = ①;
    for (int i = 1; i < N; ++i) {
        if (②) {
            candidate = i;
            count = 1;
        } else {
            if (③) {
                ④;
            } else {
            count++;
            }
        }
    }
    cout << ⑤ << endl;
    return 0;
}
CSP-J 2025 第一轮 第 38 题 原题
原题扫描(页面加载后可直接在线作答)

本小题

①处应填( )

选项

  • A. 0
  • B. 1
  • C. N
  • D. -1

答案

B

题解

①处应填 1,选择 B。

这道题的关键是看清:进入循环之前,程序已经把谁算进去了。

``cpp int candidate = 0; int count = __①__; for (int i = 1; i < N; ++i) { ``

candidate = 0 表示先把第 0 个人作为候选人;循环从 i = 1 开始,说明第 0 个人已经处理过,接下来才依次处理其余人。因此,初始时已有一个尚未被抵消的人,计数应为 1。

这里的 count 是消除过程中保留下来的计数,不是已经确认的精明人数。将它设为 1,并不意味着已经知道第 0 个人是精明人,只是记录当前候选人最初占一个名额。

程序在更换候选人时也写了:

``cpp candidate = i; count = 1; ``

这与初始化的含义完全一致:新候选人刚被选中时,先计入他自己,所以计数从 1 开始。

其他选项中,0 相当于漏掉已经选入的第 0 个人;N 把尚未处理的人也算了进去;-1 则不符合当前已有一个候选人的计数状态。

因此应填写:

``cpp int count = 1; ``

真题版权归 CCF 所有,本站仅用于非商业教学用途。页面加载后可直接在线作答,作答记录保存在本浏览器或账号中。 京ICP备2026056990号-1 京公网安备11010502062986号