「CF1382B」Sequential Nim - 题解

  • 题目大意

    \(n\) 堆石子,第 \(i\) 堆有 \(a_i\) 个。有两个人在玩取石子游戏。

    两个人轮流取石子,每次取编号最小且有石子的堆。每个人可以在一堆石子中取走若干个(至少取 \(1\) 个),当一个人没有石子可以取了,他就输了。

    现在给出每堆石子的数量,假设两人的都采用最优策略,问最后是先手 (first) 胜利还是后手 (second) 胜利。

  • 分析

    我们可以发现对于若干堆(第一堆数量大于 \(1\),有这么一个贪心的取法:

    比如第一堆堆数量为 \(n(n>1)\)先手先取 \(n-1\) 个。这样后手只能取 \(1\) 个(无法不取)。

    这样,先手就可以先取第二堆

    后几堆的取法同上,直到先手可以先取最后一堆。

    对于最后一堆,先手直接取完。获胜。

    那如果中间有一堆数量为 \(1\) 那么对于这一堆的前一堆,直接全部取完,后手只能取完这堆数量为 \(1\) 的堆。照样可以获得下一堆的先手

    以此类推。我们可以发现,影响最后结果的,只有前缀 \(1\) 的数量。

    容易发现,如果前缀 \(1\) 数量为偶数个,在轮流取完后,那么第一个非 \(1\) 堆,是先手先取。即先手会胜利。

    如果是奇数个,那么第一个非 \(1\) 堆,是后手先取。即后手会胜利。

    特殊的,如果这堆只有 \(1\)那么偶数个胜利的为后手奇数个胜利的为先手


  • 代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int Maxn=1e5+5;
    int T,n,a[Maxn];
    int main()
    {	
        scanf("%d",&T);
        while(T--)
        {	
            int cnt=0,i;
            scanf("%d",&n);
            for(i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(i=1;i<=n;i++)
                if(a[i]==1)cnt++;
                else break;
            if(i==n+1)
            {	
                if(cnt%2==0)printf("Second\n");
                else printf("First\n");
            }
            else{
                if(cnt%2==0)printf("First\n");
                else printf("Second\n");
            }
        }
        return 0;
    }
    
posted @ 2020-08-03 09:57  Rainy7  阅读(185)  评论(0编辑  收藏  举报