#HK5409. 「IOI2025」纪念品

「IOI2025」纪念品

注意事项

在 LibreOJ 上,由于语言限制,目前只支持以下语言的提交:

  • C++(标准为 C++ 17 及以上)

请在提交源代码前添加 #include "souvenirs.h"

题目描述

Amaru 在一家国外商店购买纪念品。商店有 NN 纪念品,而且每种纪念品有无限多件现货。

每种纪念品都有一个固定的价格:第 ii 种(0i<N0 \leq i < N)纪念品的价格为 P[i]P[i] 枚硬币,其中 P[i]P[i] 是一个正整数。

Amaru 知道纪念品种类是按价格降序排列的,而且所有纪念品的价格互不相同。具体来说,P[0]>P[1]>>P[N1]>0P[0] > P[1] > \cdots > P[N-1] > 0。此外,他还知道 P[0]P[0] 的值。不幸的是,Amaru 没有其他纪念品的价格信息。

为了购买纪念品,Amaru 会与卖家进行若干次交易。

每次交易由以下步骤组成:

  1. Amaru 向卖家支付一定数量(正数)的硬币。
  2. 卖家将这些硬币堆放在商店后台的桌子上,因此 Amaru 无法看到这些硬币。
  3. 卖家按顺序依次处理每种纪念品 0,1,,N10, 1, \ldots, N-1。每种纪念品在每次交易中被处理恰好一次
    • 当处理第 ii 种纪念品时,如果当前硬币堆中的硬币数量至少为 P[i]P[i],则
      • 卖家从硬币堆中移除 P[i]P[i] 枚硬币;
      • 卖家将一件第 ii 种纪念品放在桌子上。
  4. 卖家将剩余的所有硬币和桌子上的纪念品交给 Amaru。

注意,在每次交易开始前,桌上没有任何硬币或纪念品。

你的任务是指导 Amaru 进行若干次交易,使得:

  • 在每次交易中,他购买至少一件纪念品;
  • 总体上他恰好购买了 ii 件第 ii 种纪念品,其中 0i<N0 \leq i < N。注意,这意味着 Amaru 不应购买第 00 种纪念品。

Amaru 不需要最小化交易次数,而且拥有无限量的硬币供应。

实现细节

你需要实现以下函数。

void buy_souvenirs(int N, long long P0)
  • NN:纪念品的种数。
  • P0P0P[0]P[0] 的值。
  • 对每个测试用例,该函数恰被调用一次。

上述函数可以调用以下函数,来指导 Amaru 进行交易:

std::pair<std::vector<int>, long long> transaction(long long M)
  • MM:Amaru 支付给卖家的硬币数量。
  • 该函数返回一对元素。第一个元素是数组 LL,包含按顺序排列的已购买的纪念品种类。第二个元素是整数 RR,表示交易后卖家返还给 Amaru 的硬币数量。
  • 要求 P[0]>MP[N1]P[0] > M \geq P[N-1]。条件 P[0]>MP[0] > M 确保 Amaru 不购买第 00 种纪念品,而条件 MP[N1]M \geq P[N-1] 确保他至少购买一件纪念品。如果这些条件未被满足,你将收到 Output isn't correct: Invalid argument。注意,与 P[0]P[0] 不同,P[N1]P[N-1] 的值未在输入中提供 。
  • 对每个测试用例,该函数最多被调用 50005000 次。

评测程序的行为是非自适应的。 这意味着在调用 buy_souvenirs 前,价格序列 PP 是固定的。

约束条件

  • 2N1002 \leq N \leq 100
  • 对每个满足 0i<N0 \leq i < Nii,有 1P[i]10151 \leq P[i] \leq 10^{15}
  • 对每个满足 0i<N10 \leq i < N - 1ii,有 P[i]>P[i+1]P[i] > P[i+1]

子任务

子任务 分数 额外的约束条件
1 44 N=2N = 2
2 33 对每个满足 0i<N0 \leq i < Nii,有 P[i]=NiP[i] = N - i
3 1414 对每个满足 0i<N10 \leq i < N - 1ii,有 P[i]P[i+1]+2P[i] \leq P[i+1] + 2
4 1818 N=3N = 3
5 2828 对每个满足 0i<N20 \leq i < N-2ii,有 P[i+1]+P[i+2]P[i]P[i+1] + P[i+2] \leq P[i]
对每个满足 0i<N10 \leq i < N-1ii,有 P[i]2P[i+1]P[i] \leq 2 \cdot P[i+1]
6 3333 没有额外的约束条件。

例子

考虑以下函数调用。

buy_souvenirs(3, 4)

共有 N=3N = 3 种纪念品,且 P[0]=4P[0] = 4。观察到只有三种可能的价格序列 PP[4,3,2][4, 3, 2][4,3,1][4, 3, 1][4,2,1][4, 2, 1]

假设 buy_souvenirs 调用 transaction(2),且函数返回 ([2],1)([2], 1),表示 Amaru 购买了一件第 22 种纪念品,而且卖家返还了 11 枚硬币。通过观察,我们可以推断出 P=[4,3,1]P = [4, 3, 1],因为:

  • 对于 P=[4,3,2]P = [4, 3, 2]transaction(2) 会返回 ([2],0)([2], 0)
  • 对于 P=[4,2,1]P = [4, 2, 1]transaction(2) 会返回 ([1],0)([1], 0)

然后 buy_souvenirs 可以调用 transaction(3) 返回 ([1],0)([1], 0),表示 Amaru 购买了一件第 11 种纪念品,而卖家返还了 00 枚硬币。到目前为止,Amaru 购买了一件第 11 种纪念品和一件第 22 种纪念品。

最后,buy_souvenirs 可以调用 transaction(1) 返回 ([2],0)([2], 0),表示 Amaru 购买了一件第 22 种纪念品。注意,这里也可以调用 transaction(2)。至此,Amaru 共购买了一件第 11 种纪念品和两件第 22 种纪念品,符合要求。

评测程序示例

输入格式:

N
P[0] P[1] ... P[N-1]

输出格式:

Q[0] Q[1] ... Q[N-1]

这里,对每个满足 0i<N0 \leq i < Nii,购买的第 ii 种纪念品的数量为 Q[i]Q[i]