1 条题解

  • 0
    @ 2026-5-14 17:45:41

    题目解析

    我们有一个由 nn 个彩色弹珠组成的序列,两个人轮流取弹珠,Alice 先手。
    得分规则:

    1. 对每种颜色 xx,如果 Alice 至少取了一个该颜色的弹珠,得 11 分。
    2. 对每种颜色 xx,如果 Alice 取走了该颜色的 所有 弹珠,再得 11 分(即总共 22 分)。

    因此,对某种颜色:

    • 如果 Alice 取走了全部,她得 22 分。
    • 如果 Alice 取走了一部分(但不是全部),她得 11 分。
    • 如果 Alice 一颗没取,她得 00 分。

    Bob 的目标是最小化 Alice 的得分,Alice 的目标是最大化。


    关键观察

    1. 只出现一次的弹珠(unique marbles)

    如果某种颜色的弹珠数量为 11

    • 如果 Alice 取走它,她得 22 分(至少取一个 + 取完所有)。
    • 如果 Bob 取走它,Alice 得 00 分。

    这是一个双方都会争夺的对象。由于轮流取,这类颜色会 被双方轮流取走
    uu 为数量为 11 的颜色数。
    按最优玩法:

    • Alice 能取到 u2\lceil \frac{u}{2} \rceil 个这种弹珠,每个让她得 22 分。
      所以这部分得分为:
    2×u22 \times \lceil \frac{u}{2} \rceil

    2. 出现次数 ≥ 2 的颜色

    对于数量 2≥ 2 的颜色,任何玩家都无法独自取完(因为双方都会取)。
    一个经典的对称策略:如果上回合对方取了某个颜色的 第一个 弹珠,那么当前玩家就取同一个颜色的另一个弹珠,否则随便取一个。

    这个策略保证:

    • 每种这样的颜色,Alice 至少取到 11 个(得 11 分)。
    • 但 Alice 无法取完任何这种颜色(因为 Bob 会在她第一次取完后立刻取走另一个)。
    • 因此 Alice 最多得 11 分每种。

    kk 为数量 2≥ 2 的颜色数,这部分得分为:

    kk

    最终公式

    $$\text{score} = k + 2 \times \lceil \frac{u}{2} \rceil $$

    其中 u2\lceil \frac{u}{2} \rceil 在代码中可以用 (u+1)/2(u + 1)/2 实现整除。


    示例验证

    样例 1

    [1,3,1,3,4][1,3,1,3,4]
    计数:颜色 11: 22 个,颜色 33: 22 个,颜色 44: 11
    u=1u = 1k=2k = 2
    得分 = 2+2×1/2=2+2=42 + 2 \times \lceil 1/2 \rceil = 2 + 2 = 4

    样例 2

    [1,2,3][1,2,3]
    计数:1,1,11,1,1
    u=3u = 3k=0k = 0
    得分 = 0+2×3/2=2×2=40 + 2 \times \lceil 3/2 \rceil = 2 \times 2 = 4

    样例 3

    [4,4,4,4][4,4,4,4]
    计数:颜色 44: 44
    u=0u = 0k=1k = 1
    得分 = 1+0=11 + 0 = 1


    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
    上传者