#P15663. [Bulgarian2025训练营]Trick

[Bulgarian2025训练营]Trick

题目描述

魔术师 Harry 又带来了新的魔术表演。

最开始有一副牌,共 NN 张完全相同的牌,牌面上真实编号为 11NN。这些牌一开始背面朝上放在桌上,因此真实编号不可见。Harry 又在牌背上写下 11NN 的标记编号。

助手上台后,魔术过程如下:

  1. Harry 将 NN 张牌放入 BB 个盒子中,每个盒子中恰好放 KK 张牌,且 N=B×KN=B\times K。整个过程中牌不会被翻开。
  2. 助手在每个盒子内部随机打乱牌的顺序。
  3. 助手再随机打乱盒子的顺序。
  4. Harry 询问助手现在牌的顺序。助手会检查所有牌,并依次写下第一个盒子中的真实编号、第二个盒子中的真实编号,依此类推。
  5. 最后牌重新背面朝上放回桌面,Harry 可以重复上述过程。

经过若干次询问后,Harry 总是要猜出每个背面标记编号对应的真实牌号。

请编写程序 trick,帮助 Harry 尽可能快地完成魔术。若询问次数超过 QQ,观众会感到无聊,因此最多只能询问 QQ 次。

实现要求

你需要实现如下函数:

std::vector<int> trick(int N, int B, int K);

评测程序会调用该函数一次,参数含义分别为牌数、盒子数、每盒牌数。

函数应返回一个长度为 NN 的数组,表示按照 Harry 在牌背上写下的编号 11NN 的顺序,每张牌的真实编号。

你可以调用如下函数向助手询问:

std::vector<std::vector<int>> shuffle(std::vector<std::vector<int>> boxes);

其中 boxes 描述 Harry 将编号为 11NN 的牌背标记分入 BB 个盒子的方式,每个盒子中必须恰好有 KK 张牌。

函数返回助手经过“盒内打乱”和“盒子打乱”后的结果:返回的是若干盒子中的真实牌号,每个盒子内部顺序任意,盒子之间顺序也任意。

如果传入的 boxes 不是 11NN 的合法分组,会得到 Wrong answer,并显示 Invalid question

如果调用 shuffle 超过 QQ 次,也会得到 Wrong answer,并显示 Too many questions

你的程序文件 trick.cpp 必须实现函数 trick。它可以包含其他代码、函数和全局变量,但不能包含 main 函数,不能读标准输入,也不能向标准输出打印内容。

程序需要包含头文件:

#include "trick.h"

数据范围

  • 6N10006 \le N \le 1000
  • 2B,K2 \le B,K
  • N=B×KN=B\times K

子任务

子任务 分值 NN BB KK QQ 其他限制
0 - 20002000 样例通信中的牌
1 2 66 22 33 100100
2 3 33 22
3 12 - 1212 助手不会打乱盒子的顺序
4 16 1000\le 1000 N2\frac N2 22 44
5 15 22 N2\frac N2 1212
6 52 >2>2 20002000

某个子任务的得分等于该子任务内所有测试点得分的最小值乘以该子任务分值。只有测试点成功猜出全部牌号,才会得到正分。

评分方式

设某个测试点中调用 shuffle 的次数为 qq

对于子任务 0055

  • qQq\le Q,该测试点得分为 11
  • q>Qq>Q,该测试点得分为 00

对于子任务 66

  • q9q\le 9,得分为 11
  • 9<q509<q\le 50,得分按题面给定的递减公式计算;
  • 50<q50050<q\le 500,得分为 1752\frac{17}{52}
  • 500<q2000500<q\le 2000,得分为 852\frac{8}{52}
  • q>2000q>2000,得分为 00

样例通信

假设有 66 张牌,按照牌背标记 11NN 的顺序,它们的真实编号依次为:

3 1 4 5 2 6

B=3,K=2,Q=2000B=3,K=2,Q=2000

你的程序动作 评测程序动作或返回
trick(6,3,2)
shuffle({{1,2},{3,4},{5,6}}) 返回 {{6,2},{5,4},{3,1}}
shuffle({{1,3},{2,4},{6,5}}) 返回 {{3,4},{5,1},{6,2}}
return {3,1,4,5,2,6}

本地测试

本地测试提供 trick.hLgrader.cpp、样例 trick.cpp 以及样例通信中的牌。

将这些文件放在同一目录下,并将你的 trick.cppLgrader.cpp 一起编译,即可得到本地测试程序。

本地测试程序从标准输入读入:

  • 第一行:五个正整数 N,B,K,Q,SN,B,K,Q,S,分别表示牌数、盒子数、每盒牌数、最大询问次数和子任务编号;
  • 第二行:NN 个正整数,表示按照 Harry 的背面标记顺序,每张牌的真实编号。

如果没有遵守通信协议,程序会输出相应错误信息;否则若猜测成功,会输出 Correctly guessed cards.