国王游戏

1 题目描述

恰逢 H 国国庆,国王邀请 nn 位大臣来玩一个有奖游戏。

首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。

然后,让这 nn 位大臣排成一排,国王站在队伍的最前面。

排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:

排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。

注意,国王的位置始终在队伍的最前面。

输入格式

第一行包含一个整数 nn,表示大臣的人数。

第二行包含两个整数 aa 和 bb,之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来 nn 行,每行包含两个整数 aa 和 bb,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

数据范围

1≤n≤10001 \le n \le 1000, 0<a,b<100000 < a, b < 10000。

输入样例:

3
1 1
2 3
7 4
4 6

输出样例:

2

2 解析

不难发现,大臣的次序会影响枚举出来的,因此我们需要一种排序的启发式策略进行求解。

因此选择 邻项交换 来找出局部最优策略。

考虑交换 ii 与 i+1i+1 位大臣的次序,则交换前,两人获得的奖赏为:

vali=1Ri∏k=1i−1L[k],vali+1=1Ri+1Li∏k=1i−1L[k]val_i = \frac{1}{R_i} \prod_{k=1}^{i-1} L[k], \quad val_{i+1} = \frac{1}{R_{i+1}} L_i \prod_{k=1}^{i-1} L[k]

交换后,两人获得的奖赏为:

vali+1′=1Ri∏k=1i−1L[k],vali′=1Ri+1Li+1∏k=1i−1L[k]val'_{i+1} = \frac{1}{R_i} \prod_{k=1}^{i-1} L[k], \quad val'_i = \frac{1}{R_{i+1}} L_{i+1} \prod_{k=1}^{i-1} L[k]

交换前,获得奖赏较多的大臣获得的奖赏为:

∏k=1i−1L[k]×max⁡(1Ri,LiRi+1)\prod_{k=1}^{i-1} L[k] \times \max\left(\frac{1}{R_i}, \frac{L_i}{R_{i+1}}\right)

交换后,获得奖赏较多的大臣获得的奖赏为:

∏k=1i−1L[k]×max⁡(1Ri+1,Li+1Ri)\prod_{k=1}^{i-1} L[k] \times \max\left(\frac{1}{R_{i+1}}, \frac{L_{i+1}}{R_i}\right)

做差比较交换后式子,先通分再提出因式,有:

f=max⁡(Ri+1,RiLi)−max⁡(Ri,Ri+1Li+1)f = \max(R_{i+1}, R_i L_i) - \max(R_i, R_{i+1} L_{i+1})

我们的目的是使任意邻项发生交换时,获得奖赏不会增大,即若 f≤0f \le 0,则交换前才更优。

由于 Rj,LjR_j, L_j 都是正整数,故有:RjLj≥RjR_j L_j \ge R_j。

若 RiLi<Ri+1Li+1R_i L_i < R_{i+1} L_{i+1},则:

  1. Ri+1>RiLiR_{i+1} > R_i L_i 时,f=Ri+1−max⁡(Ri,Ri+1Li+1)≤0f = R_{i+1} - \max(R_i, R_{i+1} L_{i+1}) \le 0
  2. Ri+1<RiLiR_{i+1} < R_i L_i 时,f=RiLi−max⁡(Ri,Ri+1Li+1)≤0f = R_i L_i - \max(R_i, R_{i+1} L_{i+1}) \le 0

显然,交换前方案更小(优)。

若 RiLi≥Ri+1Li+1R_i L_i \ge R_{i+1} L_{i+1},则:

  1. f=RiLi−max⁡(Ri,Ri+1Li+1)≥0f = R_i L_i - \max(R_i, R_{i+1} L_{i+1}) \ge 0

显然,交换后方案更小(优)。

综上,排序方案为按 RiLiR_i L_i 升序排列。

另外本题最坏情况的前缀积为 (103)10000=1030000(10^3)^{10000} = 10^{30000},需要上高精度。

sort(seg + 1, seg + n + 1);
vector<int> prefix = {seg[0].l}, res;
for (int i = 1; i <= n; i ++ )
{
    vector<int> t = div(prefix, seg[i].r);
    if (lw(res, t)) res = t;
    prefix = mul(prefix, seg[i].l);
}
for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i];
cout << endl;

3 相关题解

暂无相关题解