QOJ.ac

QOJ

実行時間制限: 2 s メモリ制限: 512 MB 満点: 100 コミュニケーション

#5185. 千花想要作弊

統計

Chika 有一副包含 $q$ 张扑克牌的牌组,每张牌上都写着不同的正整数。她想用这些牌和学生会的朋友们玩一些游戏,但她也想赢,所以她决定偷偷在牌的背面做标记。

这些牌都是 $2 \times 2$ 的正方形,左下角坐标为 $(0, 0)$,右上角坐标为 $(2, 2)$。Chika 在每张牌的背面画上特定的图案,以便日后通过观察图案就能知道牌正面写的是什么数字。她通过以下过程绘制图案:她可以随心所欲地(也可以 0 次)选择两个具有整数坐标且相对于牌左下角的不同点 $A$ 和 $B$,并在它们之间画一条直线段。

Chika 只会绘制有效的线段,即连接两个点 $A$ 和 $B$ 的线段,且该线段上不存在其他具有整数坐标的点($A$ 和 $B$ 除外)。例如,连接 $(0, 0)$ 和 $(2, 2)$ 的线段是无效的,因为它包含了点 $(1, 1)$;但连接 $(0, 0)$ 和 $(1, 1)$ 以及连接 $(1, 1)$ 和 $(2, 2)$ 的线段都是有效的,Chika 甚至可以在同一个图案中同时画出这两条线段。此外,请注意线段是没有方向的:从 $A$ 到 $B$ 的线段与从 $B$ 到 $A$ 的线段是完全相同的。

重要的是,Chika 希望确保无论牌如何旋转,她都能识别出她的牌。牌相对于原始方向可以逆时针旋转 0、90、180 或 270 度。

你的任务是帮助 Chika 为她牌组中的 $q$ 张牌设计图案,并在之后识别出这些牌。

实现细节

这是一个包含两个阶段的交互式任务,每个阶段涉及程序的独立运行。你需要实现两个函数:

  • BuildPattern 函数,返回给定牌背面应绘制的图案。该函数在第一阶段会被调用 $q$ 次。
  • GetCardNumber 函数,返回带有给定图案(可能已旋转)的牌的数字。该函数在第二阶段会被调用 $q$ 次。

第一个函数:

std::vector<std::pair<std::pair<int, int>, std::pair<int, int>>> BuildPattern(int n);

该函数接收一个参数 $n$,即牌正面写的数字。你需要返回一个 std::vector,其中包含 Chika 为了日后识别而绘制的线段。线段由一对点表示,点由一对整数坐标 $(x, y)$ 表示,坐标相对于牌的左下角,其中 $0 \le x, y \le 2$。Chika 绘制的所有线段必须是有效的且两两不相同。保证所有 $q$ 次对 BuildPattern 的调用中,参数 $n$ 均不相同。

在接收到 $q$ 张牌的所有图案后,评测程序可能会对每个图案执行以下任意操作任意次数:

  • 将整个图案逆时针旋转 0、90、180 或 270 度。
  • 修改图案 std::vector 表示中线段的顺序。
  • 改变线段端点的顺序。(从 $A$ 到 $B$ 的线段可能变为从 $B$ 到 $A$ 的相同线段。)

第二个函数:

int GetCardNumber(std::vector<std::pair<std::pair<int, int>, std::pair<int, int>>> p);

该函数接收一个参数 $p$,即一个描述 Chika 在牌背面绘制的图案的 std::vector(基于之前对 BuildPattern 函数的返回值)。该函数必须返回牌正面写的数字 $n$。请记住,图案 $p$ 不一定是 BuildPattern 返回的原始形式;它可能经过了上述三种操作。牌的顺序也可能与第一阶段给出的顺序不同,但保证每张牌都会被使用且仅被使用一次。

数据范围

  • $1 \le q \le 10\,000$。
  • 对于所有对 BuildPattern 函数的调用,$1 \le n \le 67\,000\,000$。
  • 注意,存在能够构造图案以识别 $67\,000\,000$ 张不同牌的算法。

子任务

  • 子任务 1(2 分):$n \le 2$。
  • 子任务 2(9 分):$n \le 25$。
  • 子任务 3(15 分):$n \le 1\,000$,且评测程序在第一阶段和第二阶段之间不会旋转图案。(评测程序可能会执行其他两种操作。)
  • 子任务 4(3 分):$n \le 16\,000\,000$,且评测程序在第一阶段和第二阶段之间不会旋转图案。(评测程序可能会执行其他两种操作。)
  • 子任务 5(24 分):$n \le 16\,000\,000$。
  • 子任务 6(18 分):$n \le 40\,000\,000$。
  • 子任务 7(29 分):无额外限制。

样例

样例 1

函数调用 返回值 说明
第一阶段开始 - -
BuildPattern(3) {{{0, 0}, {2, 1}}, {{1, 1}, {2, 0}}} 我们需要为 $2 \times 2$ 尺寸牌上的数字 3 创建图案。我们决定画 2 条线段:
- 连接 $(0, 0)$ 和 $(2, 1)$,
- 连接 $(1, 1)$ 和 $(2, 0)$。
BuildPattern(1) {{{0, 1}, {0, 0}}} 我们需要为 $2 \times 2$ 尺寸牌上的数字 1 创建图案。我们决定画 1 条线段:
- 连接 $(0, 1)$ 和 $(0, 0)$。
第一阶段结束 - -
第二阶段开始 - -
GetCardNumber({{{0, 0}, {0, 1}}}) 1 我们得到一个由 1 条线段组成的图案:
- 连接 $(0, 0)$ 和 $(0, 1)$。
这与我们通过绘制线段得到的图案相同:
- 连接 $(0, 1)$ 和 $(0, 0)$。
这正是我们在第二次调用 BuildPattern 函数时返回的、具有相同方向(旋转 0 度)的图案。因此,我们返回 1。
GetCardNumber({{{1, 1}, {2, 2}}, {{1, 2}, {2, 0}}}) 3 我们得到一个由 2 条线段组成的图案:
- 连接 $(1, 1)$ 和 $(2, 2)$,
- 连接 $(1, 2)$ 和 $(2, 0)$。
这是我们在第一次调用 BuildPattern 函数时返回的图案,逆时针旋转了 90 度。因此,我们返回 3。
第二阶段结束 - -

接下来的三张图片依次表示:

  • 第一次调用 BuildPattern 返回的图案:
  • 第二次调用 GetCardNumber 接收到的参数图案,即第一个图案逆时针旋转 90 度后的结果:
  • 第二次调用 BuildPattern 返回的图案,这也是第一次调用 GetCardNumber 接收到的参数图案:

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.