P7725 珍珠帝王蟹 (Crab King) 题解

题目传送门

简要题意:

给定 \(n\) 个形如 \(+v\) 或 \(\times v\) 的操作以及初始数 \(0\),问怎样安排操作顺序能使最后的结果最大,输出其对 \(998244353\) 取模的结果。

数据范围:\(n\leq 10^5,2\leq \left|v\right|\leq 10^6\)

Subtask 1

\(O(n!)\) 枚举操作顺序,暴力判断最大值即可,注意到最大值不会超过 \(5^9=1953125\),所以不必考虑溢出。

Subtask 2

对于 \(v>0\) 的情况,假设我们已经得到了一个中间值 \(w\),考虑两个操作 \(+m\) 和 \(\times n\),怎样安排顺序才能最大化结果?

先加再乘:\((w+m)n=wn+mn\)

先乘再加:\(wn+m\)

显然先加、再乘是优于先乘、再加的。

所以总体的操作顺序就是先加、再乘正数

Subtask 3

对于所有乘法操作保证 \(v>0\),即在 Subtask 2 的基础上多出了减法操作。

那么如何让减法对最后的结果影响最小?

首先,乘法要放在加法之后,才能保证其结果更优。

其次,减法不能在乘法或加法之前,不然会让乘法增大减法对答案的影响。

所以先加、再乘正数、最后减是最优方案。

Subtask 4

对于所有加法操作保证 \(v>0\),即在 Subtask 2 的基础上多出了乘负数的操作。

不会真有人还不知道负负得正吧。

如果乘负数的操作有偶数个,就和 Subtask 2 类似,只需要先加、再乘负数和正数即可。

那如果乘负数的操作有奇数个呢?

样例 \(1\) 的说明提示我们,可以在第一次操作前,把 \(0\) 乘上一个负数,这样就相当于让这个操作 “凭空消失” ,剩下的就和上面一致了。

Subtask 5

其实和上面的分析类似,我们需要考虑的就是如何让减法和乘负数对结果的影响最小 (或者说是对结果的贡献最大) 。

但是乘负数的操作数的奇偶性也会对顺序有影响。

所以按乘负数的操作数的奇偶进行分类。

  • 乘负数的操作数是奇数。

不妨设有 \(2k+1\) 个操作。

对于减法操作来说,只需要让它们之和乘奇数个负数就能变成正数。

最优解是先减、再乘负数、再加、最后乘正数?显然还有更优的做法。

对于乘 \(2k\) 个较小的负数而言,他们是可以当作乘 \(2k\) 个较大的正数,而剩下的一个最大的负数就已经可以把减出来的负数变为正数了。

所以最优解应该是先减、再乘最大的负数、再加、最后乘剩下的负数和正数

  • 乘负数的操作数是偶数。

实话实说,比赛时这种情况卡了我很久。

一开始想的是跟奇数类似,再加上 Subtask 4 中先乘最大的负数的操作,也就是:

先乘最大的负数、再减、再乘第二大的负数、再加、再乘剩下的负数和正数。

但是提交之后发现这并不是正解。

思考一下:为什么我们在上一种情况中要把负数变成正数后再计算?

  1. \(2k\) 个乘负数的操作能乘出一个正数,但是我们有 \(2k+1\) 个。
  2. 而且这多出来的一个操作刚好能让减出来的负数变成正数。

那我们现在有 \(2k\) 个操作,是不是也可以让他多出来一个呢?

相信大家看到这里都能基本理解我的意思了,这里的操作与上一种情况基本相反。

既然我们想要剩下 \(2k-1\) 个乘负数的操作,我们就要让之前的所有操作得到的结果变成一个最小的负数。

所以最优解实际上是先加、再乘最大的负数、再减 (这里得到了最小的负数) 、最后乘剩下的负数和正数

然而现在就对了吗?

对于 Subtask 3 (没有乘负数操作) 的情况,它的操作数确实是偶数,但我们得不到想要的最小负数,所以实际上这个做法只适用于操作数 \(\geq 2\) 的情况,对于操作数 \(=0\) 的情况,只需要特判并采用 Subtask 3 的做法即可。