SP9934 ALICE - Alice and Bob【题解】

· · 题解

Update

博弈论

复杂度:O(TN),应该是最优复杂度,读入 O(N),判断 O(1),题解首杀。
此外,也是码量最小的解法。

我们设 most 为除去石子数量为 1 的堆后的最大操作总数,cnt 为石子数量为 1 的堆数。

当拿走只有 1 个石子的堆时,先后手会发生变化,因为这相当于先合并再拿走 1,是两次操作,然而你只用一次就做到了,这是这道题的关键。

假设 cnt 为偶数,后手不需要改变先后,则此时无论先手进行啥操作,结果都取决于后手的决定(被动优势,建议和同伴试试)。

综上所述 cnt\bmod 2=1 或者 most\bmod 2=1 时先手必胜。

但是当 most\le2 时,结论不成立,此时的 most 可以不讨论(因为一定是偶数),就相当于只有 cnt1 单取,此时我们一个个讨论。

  1. 0$ 个 $1
    • 显然,先手必输。
  2. 1$ 个 $1
    • 显然,先手必赢。
  3. 2$ 个 $1
    • 先手合并两个 1,先手必赢。
  4. 3$ 个 $1
    • 先手必输,自己推一下即可。
  5. 4$ 个 $1
    • 先手拿走一个,变成情况 4,先手必赢。
  6. 5$ 个 $1
    • 先手不想改变先后,合并两个,对手无论怎样一定要取走一张,此时先手拿到被动优势,先手必赢。

综上所述

\text{Code:}
#include <bits/stdc++.h>

using namespace std;

int T;

int n;

int main() 
{
    scanf("%d",&T);
    for(int i=1;i<=T;i++)
    {
        scanf("%d",&n);
        int most=0,cnt=0;
        for(int x,j=1;j<=n;j++)
        {
            scanf("%d",&x);
            if(x==1)
                cnt++;
            else 
                most+=x+1;
        }
        most--;
        if(most<=2)
        {
            if(cnt%3)
                printf("Case #%d: Alice\n",i);
            else 
                printf("Case #%d: Bob\n",i);
        }
        else
            if(cnt%2==1||most%2==1)
                printf("Case #%d: Alice\n",i);
        else 
            printf("Case #%d: Bob\n",i);
    }
    return 0;
}