zoukankan      html  css  js  c++  java
  • [JZOJ4024] [佛山市选2015] 石子游戏 解题报告

    Description

        Alice 和 Bob 总喜欢聚在一起玩游戏(T_T),今天他(她)们玩的是一款新型的取石子游戏。游戏一开始有N堆石子,Alice 和 Bob 轮流取出石子。在每次操作中,游戏者必须选择其中的一堆石子,并作出下列的其中一种操作:
    (1)移去整堆石子
    (2)假设石子堆中有X颗石子,取出Y颗石子,其中1<=Y,(Y,X)=1    
    游戏结束的条件是:取出最后一颗石子的人胜出。众所周知,Alice和Bob都是绝顶聪明的,假设他们在游戏中都采取最优的策略,问最后谁会胜出游戏呢?

    Alice先取。

    Input

        第一行包含一个整数T,表示测试数据的组数。
        接下来T组测试数据,在每组数据中,第一行包含一个整数N,表示有多少堆石子。第二行N个正整数,分别表示每堆有多少颗石子。

    Output

        每组测试数据输出一行,表示获胜者的名字(Alice 或者 Bob)。

    Sample Input

    3
    3
    3 5 6
    4
    2 3 6 9
    5
    3 2 1 1000000 999999

    Sample Output

    Alice
    Bob
    Alice
     

    Data Constraint

    20%的数据,N<=5,每堆石子数量少于10
    100%的数据,T<=100,N<=100,每堆石子数量不大于1,000,000

    题目大意就不解释了

    考虑构造这个游戏的SG函数

    SGi = mex ( { SGi­ }( i, j )=1 ∪ { 0 } ) 其中 mex 表示集合中最小没有出现过的自然数

    为什么是这样的呢?我们联想到传统的取石子游戏,并且由于(Y,X)是互质的,(X,X-Y)也是互质的。i=X,j=X-Y

    下面我们讨论这个SG函数的性质:

    首先 SG0 = 0(终止态)。

    若 i 是质数,那么对于小于 i 的所有正整数都可以被取到,那么 SGi则应为之前出现过的所有 SG 值中最大者+1,我们不难发现质数们的 SG 值是递增的。

    若 i 是一个合数,那么 i 肯定存在某个因子为前面出现过的质数,于是 SGi 最多为该质因子的 SG 值。又有质数们的 SG 值是递增的,那么 SGi 就应为最小质因子的 SG 值了。

    我们发现合数必定不能产生新的 SG 值,它必定为其某个质因子的 SG 值。 于是第 k 个质数的 SG 值就是 k+1 了。 类似线性筛质数的原理,我们可以线性筛出 SG 值了。

    下面讲解分石子问题:

    NIM问题是博弈论经典问题,一个典型的组合游戏问题,很多游戏问题都可以规约到Nim游戏问题。Nim游戏问题是一个ICG(Impartial Combinatorial Games)问题;

    ICG问题的特征是:

    1.两个人参与,交替走棋;

    2.可能的走法在一个有限的集合里选取;

    3.游戏局面无后效性,未来与过去无关;

    4.如果某选手无法走动,则判负;

    Nim的理论

    游戏状态只分两种:当前先手必胜,当前先手必败;前者称为N位置,后者称为P位置;

    更为严谨的定义是:

    终止状态是P位置;

    能够移动到P位置的状态时N位置;

    只能到N位置的状态时P位置;

    简单地说,就是在这个博弈中,给定n堆物品,第i堆物品有Ai个。两名玩家同时行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者胜利。两人都采取最优策略,问先手能否必胜

    定理:

    NIM博弈先手必胜,并且仅当A1 xor A2 xor ... xor An!=0

    证明:

      所有的物品都被取光是一个必败局面(对方取走了最后一个物品,已经取得胜利),此时显然有A1 xor A2 xor ... xor An=0。

      对于任意一个局面,若A1 xor A2 xor ... xor An = x != 0。设x的二进制最高位的1在k位,那么至少存在一堆石子Ai,它的第k位是1。显然Ai xor x < Ai,我们就从Ai堆中取走若干个石子,让它变成Ai xor x,就得到了一个各堆石子异或起来等于0的局面。

      对于任意一个局面,如果A1 xor A2 xor ... xor An=0,那么无论如何取石子,得到的局面下各堆石子异或起来都不为0.可用反证法证明,假设Ai被取成了Ai0,并且A1 xor A2 xor ... xor Ai0 xor ... xor An = 0,由异或运算的消去律得Ai0=Ai,与“不能不取石子矛盾”

      综上所述,再有数学归纳法可知,A1 xor A2 xor ... xor Ai0 xor ... xor An !=0,为必胜局面,一定存在必胜一种行动让对手陷入各堆石子都异或成0的情况。而在必败局面里,无论什么行动,都会让对手陷入各堆石子都异或成不为0的情况的必胜局面。

    证毕

    #include<cstdio>
    using namespace std;
    
    int p[1000010],f[1000010],SG[1000010];
    int num,n,ass,t;
    void get(){
        for (int i=2; i<1000010; i++){
            if(!f[i]) p[++num]=i,SG[i]=num+1;
            for (int j=1; j<=num && (j==1 || i%(p[j-1])) && p[j]*i<1000010; j++)
                f[p[j]*i]=-1,SG[p[j]*i]=j+1;
        }
    }
    
    int main()
    {
        SG[1]=1;
        get();
        scanf("%d",&t);
        for(int i=1; i<=t; i++,ass=0)
        {
            int j;
            scanf("%d",&j);
            for(;j;j--)
            {
                int x;
                scanf("%d",&x);
                ass^=SG[x];
            }
            printf(ass?"Alice
    ":"Bob
    ");
        }
    }
  • 相关阅读:
    嵌入式培训学习历程第二十四天
    嵌入式培训学习历程第二十三天
    嵌入式培训学习历程第二十二天
    嵌入式培训学习历程第二十一天
    嵌入式培训学习历程第二十天
    嵌入式培训学习历程第十九天
    嵌入式培训学习历程第十八天
    嵌入式培训学习历程第十七天
    嵌入式培训学习历程第十六天
    系统编程之进程的创建.僵尸与孤儿进程
  • 原文地址:https://www.cnblogs.com/xxzh/p/9314640.html
Copyright © 2011-2022 走看看