1 条题解
-
0
题目解析
我们有一个由 个彩色弹珠组成的序列,两个人轮流取弹珠,Alice 先手。
得分规则:- 对每种颜色 ,如果 Alice 至少取了一个该颜色的弹珠,得 分。
- 对每种颜色 ,如果 Alice 取走了该颜色的 所有 弹珠,再得 分(即总共 分)。
因此,对某种颜色:
- 如果 Alice 取走了全部,她得 分。
- 如果 Alice 取走了一部分(但不是全部),她得 分。
- 如果 Alice 一颗没取,她得 分。
Bob 的目标是最小化 Alice 的得分,Alice 的目标是最大化。
关键观察
1. 只出现一次的弹珠(unique marbles)
如果某种颜色的弹珠数量为 :
- 如果 Alice 取走它,她得 分(至少取一个 + 取完所有)。
- 如果 Bob 取走它,Alice 得 分。
这是一个双方都会争夺的对象。由于轮流取,这类颜色会 被双方轮流取走。
设 为数量为 的颜色数。
按最优玩法:- Alice 能取到 个这种弹珠,每个让她得 分。
所以这部分得分为:
2. 出现次数 ≥ 2 的颜色
对于数量 的颜色,任何玩家都无法独自取完(因为双方都会取)。
一个经典的对称策略:如果上回合对方取了某个颜色的 第一个 弹珠,那么当前玩家就取同一个颜色的另一个弹珠,否则随便取一个。这个策略保证:
- 每种这样的颜色,Alice 至少取到 个(得 分)。
- 但 Alice 无法取完任何这种颜色(因为 Bob 会在她第一次取完后立刻取走另一个)。
- 因此 Alice 最多得 分每种。
设 为数量 的颜色数,这部分得分为:
最终公式
$$\text{score} = k + 2 \times \lceil \frac{u}{2} \rceil $$其中 在代码中可以用 实现整除。
示例验证
样例 1
计数:颜色 : 个,颜色 : 个,颜色 : 个
,
得分 =样例 2
计数:
,
得分 =样例 3
计数:颜色 : 个
,
得分 =
C++ 代码实现
#include <bits/stdc++.h> using namespace std; int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); vector<int> cnt(n, 0); for (int i = 0; i < n; ++i) { int x; scanf("%d", &x); --x; // 颜色值从 0 开始便于计数 cnt[x]++; } int uniqueColors = 0, multipleColors = 0; for (int i = 0; i < n; ++i) { if (cnt[i] == 1) { uniqueColors++; } else if (cnt[i] > 1) { multipleColors++; } } int ans = multipleColors + ((uniqueColors + 1) / 2) * 2; printf("%d\n", ans); } return 0; }
- 1
信息
- ID
- 7054
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者