Alice 和 Bob 在玩一个游戏。他们轮流操作,Alice 先手。在每一轮中,玩家需要选择一个写在黑板上的数,并擦掉它。
游戏会在 n 轮后结束。令 s 为 Alice 擦掉的数之和。若 L \le s \le R,则 Alice 胜利,反之 Bob 胜利。你需要输出当两方都采取最优策略情况下的赢家。
## $\text{solution}
记 S = \sum_{1\le i\le n} a_i,S_A 为 Alice 擦掉的数之和,S_B 为 Bob 擦掉的数之和。
记一个长为 m 序列 b_i 的邻项差分 \text{diff }b = (b_2 - b_1) + (b_4 - b_3) + \cdots + (b_m - b_{m-1})。
首先转化题意。条件 L \le S_A \le R 可以通过整体乘 2 减 S 转化为 2L - S \le S_A - S_B \le 2R - S。随后设 x = S - (L + R),整体加 x 后变为 L - R \le x + S_A - S_B \le R - L,即 |x + S_A - S_B| \le R - L。
因此有转化后的问题:
给定整数 x。两人轮流操作,每次选择一个没有选过的数字 a_i。在 Alice 的回合,置 x=x + a_i,而在 Bob 的回合置 x=x - a_i。最终的分数即为 x 的绝对值。Alice 的目标是最小化这个值,而 Bob 的目标是最大化它。求当两方都采取最优策略情况下的赢家。
不妨假设 a_i 升序排列。我们断言,最终的分数可以通过如下方式求得:
选择整数 p,将 p, p + x, a_1, a_2,\cdots, a_n 升序排列得到 A_i。令 p 的答案为 \text{diff }A 的值。
最终的分数即为所有可能的 p 的答案中的最小值。
容易发现 p 所有对答案有贡献的取值为 p = a_i。对于 p 的某一确定取值可以在 O(n) 的时间复杂度内计算答案,取其中最小值作为最终分数即可。
因此有总时间复杂度 O(n^2) 的算法。
假设已经证明了对 Bob 来说 n=k 的情况是成立的,现在需要证明对 Alice 来说 n=k + 1 的情况也是成立的。
Alice 的目标等价于将其中一个 a_i 更换为 a_i + x,使得 Bob 的分值最小。选择 a_i 对应着选择 p = a_i,这样的策略肯定能够产生可能得到的分数中最小的值,因此对 Alice 来说 n=k + 1 的情况通过该方式计算是正确的。
假设已经证明了对 Alice 来说 n=k + 1 的情况是成立的,现在需要证明对 Bob 来说 n=k+2 的情况也是成立的。
我们将 Bob 可选的 n-1 个整数与目前的 x 一同进行升序排序,得到序列 b_i。令 b_s = x。如果 Bob 在本轮中选择了 b_t(s \neq t),那么 Alice 可以选择 p=b_t 来得到分数 \text{diff }b。因此该值是分数的一个上界。
这个上界是可以取到的。不妨假设 s 是奇数。如果 Bob 在 s=1 时选择 t=n,在其余时刻选择 t = s-1,最终的分数就是该值。当 s 为偶数的时候类似:当 s=n 时选择 t=1,在其余时刻选择 t =s+1 即可。
根据数学归纳法,原断言成立。
总时间复杂度 O(n^2)。
\text{code : }
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
int n, l, r, a[5005], s;
vector<int> ans;
signed main() {
cin >> n >> l >> r;
rep(i,1,n) cin >> a[i], s += a[i]; s -= l + r;
sort(a + 1, a + 1 + n);
int ret = LLONG_MAX, now;
rep(i,1,n) {
ans.clear(); now = 0;
rep(j,1,n) if (i != j) ans.emplace_back(a[j]);
ans.insert(lower_bound(ans.begin(), ans.end(), a[i] + s), a[i] + s);
for (int i = 0; i < ans.size(); i += 2) now += ans[i + 1] - ans[i];
ret = min(ret, now);
} puts(abs(ret) <= r - l ? "Alice" : "Bob");
}