#P11984. [JOIST 2025] 占卜 3 / Fortune Telling 3

    ID: 14485 远端评测题 2000ms 1024MiB 尝试: 0 已通过: 0 难度: 7 上传者: 标签>2025交互题Special Judge通信题JOISC/JOIST(日本)

[JOIST 2025] 占卜 3 / Fortune Telling 3

题目背景

请使用 C++ 20 提交。不要引入 anna.hbruno.h,并在代码头加入以下语句:

int DrawCard(int);

题目描述

这是一道通信题。交互库是非自适应的。

Anna 和 Bruno 在玩一种用卡牌进行的占卜游戏 QQ 次,规则如下。

  1. 有许多上面写着 0011 的卡牌叠成一堆。Anna 从牌堆中一次抽出 NN (=900=900) 张卡牌。Anna 和 Bruno 知道 NN 的值。

  2. 每次抽到卡牌时,她会决定是弃掉这张牌还是将其放到桌上。

    • 如果她选择将牌放到桌上,她会把这张牌插入桌上的卡牌序列中。
    • 形式化地,当桌上有 ll 张卡牌时,她选定非负整数 xx0xl0 \leq x \leq l),并将这张牌放在桌上从左数第 xx 张卡牌右侧。
      • x=0x = 0 时,她将这张牌放在桌上卡牌序列的最左侧。
  3. 当 Anna 抽完并处理完 NN 张卡牌后,她的操作结束。占卜结果是这 NN 张卡牌中上面写着数字 11 的卡牌数量。

  4. 当 Anna 结束操作后,Bruno 会看到桌上的卡牌序列。基于这些信息,他需要猜出占卜结果。

如果 Bruno 猜对了,占卜就算成功。

当桌上的卡牌越少时,占卜被认为越高明。

请编写一个程序,实现 Anna 和 Bruno 的策略,使得全部 QQ 次占卜都成功。

在本题中,Anna 放在桌上的卡牌越少,得分越高。

实现细节

你不应该,也不需要实现 main 函数。

在洛谷上评测时,你只需要提交一个文件。

对于 Anna 的策略,你应该实现以下的函数:

void Anna(int N);

该函数将被调用 QQ 次。第 ii 次调用表示第 ii 次占卜的过程。

参数 NN=900N=900)代表卡牌的数量。

每次占卜,该函数必须调用以下的函数 (N+1)(N+1) 次:

int DrawCard(int x);

使用此函数,Anna 从牌堆中抽卡,并选择丢弃或放置在桌面上。她通过第 jj 次调用(1jN1 \leq j \leq N)的返回值获取第 jj 张卡片上的数字。她通过第 kk 次调用(2kN+12 \leq k \leq N + 1)的参数指定对第 (k1)(k - 1) 张卡片的操作。

  • jj 次调用(1jN1 \leq j \leq N)的返回值为 0011,表示第 jj 张卡片上的数字。
    • 特别地,第 (N+1)(N + 1) 次调用的返回值为 1-1,表示 Anna 已完成抽卡。
  • 11 次调用的参数 xx 必须为 1-1,否则程序将被判定为 Wrong Answer [1]\texttt{Wrong Answer [1]}
  • kk 次调用的参数 xx 表示对第 (k1)(k - 1) 张卡片的操作:
    • x=1x = -1,则丢弃该卡片;
    • 0x0 \leq x,则将卡片放置在桌面上当前最左数第 xx 张卡片的右侧;当 x=0x = 0 时,卡片置于桌面序列的最左侧。
    • 参数需满足 1xl-1 \leq x \leq lll 为当前桌面卡片数),否则程序将被判定为 Wrong Answer [2]\texttt{Wrong Answer [2]}
  • 若调用 DrawCard 函数的次数不为 (N+1)(N + 1),程序将被判定为 Wrong Answer [3]\texttt{Wrong Answer [3]}

对于 Bruno 的策略,你应该实现以下的函数:

int Bruno(int N, int L, std::vector<int> C)

该函数在每次调用 Anna 函数后被调用恰好一次,总计 QQ 次。

ii 次调用(1iQ1 \leq i \leq Q)对应第 ii 次占卜流程,需返回 NN 张卡牌中上面写着数字 11 的卡牌数量。

  • 参数 NN 表示 Anna 抽取的卡片总数。
  • 参数 LL 表示桌面上的卡片数量。
  • 参数 CC 为长度为 LL 的数组,其中 C[l1]C[l-1] 表示桌面上第 ll 张最左侧卡片(1lL1 \leq l \leq L)的数字。
  • 若返回值不等于 NN 张卡牌中上面写着数字 11 的卡牌数量,程序将被判定为 Wrong Answer [4]\texttt{Wrong Answer [4]}

注意事项

  • 交互库是非自适应的
  • 程序可定义其他内部函数或全局变量,但需在匿名命名空间中声明以避免冲突。
  • 由于洛谷评测系统的限制,Anna 和 Bruno 将在同一进程中运行。请注意清空。
  • 禁止使用标准输入输出或通过其他方式与外部文件通信,但可将调试信息输出至标准错误流。

编译与测试

下载附件中的压缩包,将以下文件置于同一目录:

  • grader.cpp\boldsymbol{grader.cpp}
  • Anna.cpp\boldsymbol{Anna.cpp}
  • Bruno.cpp\boldsymbol{Bruno.cpp}
  • Anna.h\boldsymbol{Anna.h}
  • Bruno.h\boldsymbol{Bruno.h}

运行以下命令编译:

g++ -std=gnu++20 -O2 -o grader grader.cpp Anna.cpp Bruno.cpp

或直接运行压缩包中的 compile.sh\boldsymbol{compile.sh}

./compile.sh

输入格式

Sample Grader 输入格式如下:

QQ NN A1,1A_{1,1} A1,2A_{1,2} \cdots A1,NA_{1,N}
A2,1A_{2,1} A2,2A_{2,2} \cdots A2,NA_{2,N}
\vdots
AQ,1A_{Q,1} AQ,2A_{Q,2} \cdots AQ,NA_{Q,N}

输出格式

Sample Grader 会向标准输出和标准错误流输出以下信息:

  • 若程序被判定为正确,Sample Grader 将以 Accepted: 100\texttt{Accepted: 100} 格式输出桌面上卡片数量的最大值。
  • 若程序被判定为错误,Sample Grader 将以 Wrong Answer [1]\texttt{Wrong Answer [1]} 格式输出错误类型。

若程序同时满足多个错误类型的条件,Sample Grader 仅报告其中一个。当检测到错误条件时,Sample Grader 可能终止执行。

2 5
0 1 0 0 1
1 1 0 1 0
Accepted: 5

提示

样例交互

样例输入包含 Q(=2)Q (= 2) 次占卜流程,Anna 从牌堆抽取的卡片数为 N(=5)N (= 5)

调用 返回值 调用 返回值
Anna(5) \texttt{Anna(5) } DrawCard(-1)\texttt{DrawCard(-1)} 00
 \texttt{ } DrawCard(0) \texttt{DrawCard(0) } 11
DrawCard(-1)\texttt{DrawCard(-1)} 00
DrawCard(1) \texttt{DrawCard(1) }
DrawCard(-1)\texttt{DrawCard(-1)} 11
DrawCard(1) \texttt{DrawCard(1) } 1-1
Bruno(5, 3, [0, 1, 0]) \texttt{Bruno(5, 3, [0, 1, 0]) } 22  \texttt{ }
Anna(5) \texttt{Anna(5) } DrawCard(-1)\texttt{DrawCard(-1)} 11
 \texttt{ } DrawCard(0) \texttt{DrawCard(0) }
DrawCard(1) \texttt{DrawCard(1) } 00
DrawCard(2) \texttt{DrawCard(2) } 11
DrawCard(-1)\texttt{DrawCard(-1)} 00
DrawCard(1) \texttt{DrawCard(1) } 1-1
Bruno(5, 4, [1, 0, 1, 0])\texttt{Bruno(5, 4, [1, 0, 1, 0])} 33  \texttt{ }

第一次占卜流程的操作步骤如下:

  1. Anna 抽取第 11 张卡,数字为 00
  2. Anna 选择将卡片置于桌面最左侧,桌面序列变为 00。接着抽取第 22 张卡,数字为 11
  3. Anna 选择丢弃此卡。随后抽取第 33 张卡,数字为 00
  4. Anna 选择将此卡放置在桌面上第 11 张最左侧卡片的右侧,桌面序列变为 0,00, 0。接着抽取第 44 张卡,数字为 00
  5. Anna 选择丢弃此卡。随后抽取第 55 张卡,数字为 11
  6. Anna 选择将此卡放置在桌面上第 11 张最左侧卡片的右侧,桌面序列变为 0,1,00, 1, 0

此时,Bruno 看到的桌面序列为 0,1,00, 1, 0,推断 Anna 抽取的卡片中数字为 11 的数量为 22(正确)。桌面上卡片数为 L=3L = 3

第二次占卜流程中,桌面上卡片数为 L=4L = 4

注:此样例输入不满足题目约束。附件压缩包中,sample-01-in.txt 对应样例输入 1,sample-02-in.txt 为满足约束的样例输入。

数据范围

  • 1Q1001\le Q\le 100
  • N=900N=900
  • 1iQ,1jN\forall 1\le i\le Q, 1\le j\le NAi,j{0,1}A_{i,j}\in \{0,1\}

计分方式

若程序在任何测试用例中被判定为 Wrong Answer [1]  [4]\texttt{Wrong Answer [1] – [4]}(见【实现细节】)、TLE、MLE 或 RE 等,则得 00 分。

若程序在所有测试用例中均被判定为正确,则得分由所有测试用例中所有占卜流程内调用 DrawCard 函数时参数满足 0x0 \leq x 的最大次数决定。

设该次数为 LL,得分规则如下:

条件 得分
500<L500 < L 33
14<L50014 < L \leq 500 $\displaystyle \left\lfloor100 \times \left( \frac{2.5}{L - 11.5} \right)^{0.35}\right\rfloor$
L14L \leq 14 100100