#P17245. [IOI 2026] 划分 / Partition
[IOI 2026] 划分 / Partition
题目描述
Temur(帖木儿)和他的助手 Ulug'bek(兀鲁伯)正在为“乌兹别克斯坦达人秀”准备一个魔术表演。
这个魔术的核心在于 Temur 需要解决以下划分问题:将一批给定的正整数划分成 个非空组,使得每个组中的元素之和相等。换言之,这批整数中的每个整数都必须恰好被分配到 个组中的一个,且每个组中的元素之和必须相等。例如,若给定的这批整数为 且 ,一种合法的划分可以是 、 和 。此时,每个组中的元素之和均为 。
魔术表演流程如下:
- Ulug'bek 和 Temur 分别进入不同的隔间,彼此无法交流。
- 裁判向 Ulug'bek 提供一个长度为 的正整数数组 (即 ),其中每个元素的值都在 到 之间(包括 和 )。裁判同时把 的值告知 Ulug'bek。
- Ulug'bek 选择至多 个整数(不需要互不相同),作为新元素添加到数组 中。每个新添加的整数也必须介于 到 之间(包括 和 )。
- 裁判将 Ulug'bek 选择的整数添加到原数组。这个扩展后的数组将按非递减顺序排序,并与 的值一并交给 Temur。
- Temur 必须对这个扩展且已排序的数组求解划分问题。
你的任务是为 Temur 和 Ulug'bek 设计并实现策略。可以证明,在给定约束条件下,无论裁判提供怎样的数组 ,均存在一种策略使他们能够成功解决划分问题。
实现细节
你要实现两个函数。
为 Ulug'bek 实现的函数为:
std::vector<int> add_numbers(std::vector<int> A, int K, int M)
- :长度为 的数组,表示交给 Ulug'bek 的原始数组。
- :要求的划分组数;注意,Ulug'bek 可以至多添加 个整数到数组中。
- :每个原始和新增整数允许的最大值。
- 对于每个测试用例,该函数恰好被调用一次。
该函数应返回一个数组 ,包含 Ulug'bek 希望添加到原始数组中的整数。设 为数组 的长度。
- 不能超过 。
- 中的每个元素的值必须介于 到 之间(包括 和 )。
为 Temur 实现的函数为:
std::vector<int> find_partition(std::vector<int> B, int K)
- :长度为 的整数数组,包含来自 的原始整数以及 Ulug'bek 添加的整数。数组 的元素已按非递减顺序排序。
- :要求的划分组数。
- 对于每个测试用例,该函数恰好被调用一次。
该函数应返回一个数组 ,给出将 划分成 个不相交组的方案。
- 的长度应为 。
- 对于满足 的每个 , 表示 所属的组的编号。
- 组的编号应为从 到 ,即对于每个 ,必须满足 。
- 对于 到 (包含边界)之间的每个 ,必须存在至少一个 ()使得 。
- 个组中,每个组所分配的元素之和必须相同。
在实际评测中,调用上述函数的程序将运行恰好两次。
- 在程序的第一次运行中:
add_numbers被恰好调用一次。- 评测系统将由所返回的数组计算出数组 。
- 在程序的第二次运行中:
find_partition被恰好调用一次。
输入格式
N K M
A[0] A[1] ... A[N-1]
输出格式
在 add_numbers 调用完成后,评测程序示例将:
- 计算排序后的数组 。
- 按以下格式输出数组 和 ,并在最后跟着一个空行:
S
C[0] C[1] ... C[S-1]
B[0] B[1] ... B[N+S-1]
在 find_partition 调用完成后,评测程序示例输出:
L
P[0] P[1] ... P[L-1]
其中, 为 find_partition 返回的数组 的长度。
提示
例子
考虑以下调用:
add_numbers([8, 2, 9, 6, 1, 5, 5], 3, 9)
在这个例子中,。我们要将这些数字划分成 个组。Ulug'bek 可以添加在 到 之间的数字。
该函数可以返回 ,表示 Ulug'bek 决定添加 个新整数: 和 。两个元素均在 到 之间,因此这是符合要求的。
扩展后的数组经排序后,通过以下函数调用交给 Temur:
find_partition([1, 2, 4, 5, 5, 5, 6, 8, 9], 3)
我们可以将该数组中的整数划分为这三个组:、 和 。可以看到,每个组中的元素之和均等于 。该函数应返回数组 来给出此划分结果。
约束条件
- 对于满足 的每个 ,均有 。
子任务
| 子任务 | 分数 | 额外的约束条件 |
|---|---|---|
| 没有额外的约束条件。 |