AcWing博弈论——Nim游戏

题目:Nim游戏
此题AC代码:

import java.util.Scanner;
class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int ans=0;
        for(int i=0;i<n;i++){
            ans^=in.nextInt();
        }
        if(ans==0){
            System.out.println("No");
        }else{
            System.out.println("Yes");
        }
    }
}

1.结论:

一共有n堆石子,各堆石子数目分别是:a1 a2 a3 ... an
如果a1 ^ a2 ^ a3 ^ ... ^an = 0,则先手必败;
如果a1 ^ a2 ^ a3 ^ ... ^an ≠ 0,则先手必胜。

2.首先来证明以下结论:

1.0 ^ 0 ^ 0 ^... ^ 0 =0。
  说明:结果各个堆的石子数目都是0,即没有石子可以拿,则必败。
2.a1 ^ a2 ^ a3 ^ ... ^ an=x(≠0)时,一定可以从其中一个堆中拿出几个石子从而达到a1 ^ a2 ^ a3 ^ ... ^ an=0的状态。
  说明:各个堆的石子数目异或起来结果不是0,一定可以通过拿石子使异或的结果变成是0的局面。
  即:当前局面必胜,可以通过拿石子转成必败局面,并将此必败局面留给对方。
3.a1 ^ a2 ^ a3 ^ ... ^ an=0时,无论怎么拿,拿之后的a1 ^ a2 ^ a3 ^ ... ^ an的结果一定不为0。
  说明:各个堆的石子数目异或起来结果是0,不管怎么拿石子,异或的结果都不会是0。
  即:当前的局面必败,一定不可以转成必败的局面,即留给后手的局面是必胜的,则自己必败。

3.证明过程:

证明第2点:a1 ^ a2 ^ a3 ^ ... ^ an=x(≠0)时,一定可以从其中一个堆中拿出几个石子从而达到a1 ^ a2 ^ a3 ^ ... ^ an=0的状态。

假设x的二进制表示中最高一位1在第k位,则a1~an中必然存在一个数ai的第k为是1(因为所有数的第n位都是0的话,异或的结果第k位不会是1)。
得到 :ai ^ x < ai(左右两个数的前k位一样,左边的数的第k位经过异或变成了0,所以左边的数小于右边的数)
所以:ai - (ai ^ x) >0 成立
从石子数目是ai的堆里拿出ai - (ai ^ x),即第ai堆的数目变成了ai-[ai - (ai ^ x)]=ai ^ x
则拿完后,有:a1 ^ a2 ^ ... ^ ai ^ x  ^ ... ^an=(a1 ^ a2 ^ ... ^an) ^ x =x ^ x=0
得证。
证明第3点:a1 ^ a2 ^ a3 ^ ... ^ an=0时,无论怎么拿,拿之后的a1 ^ a2 ^ a3 ^ ... ^ an的结果一定不为0。

反证法:
假设从任意一堆石子数目是ai的堆中拿出若干石子后数目变成了ai ’
则:a1 ^ a2 ^ ... ^ ai ’  ^ ... ^an=0
原来:a1 ^ a2 ^ ... ^ ai ^ ... ^an=0
上下异或:ai ^ ai ’ = 0 ^ 0
得到:ai = ai ’
假设不成立。
得证。

4.总结:
若此时拿到的状态是异或为非0,由第二点得,可以将这个状态转换成异或为0的状态抛给后手,后手必败,则自己必胜。
若此时拿到的状态是异或为0,由第三点得,无论如何都不能将此状态转换成异或结果是0的状态,即后手必胜,则自己必败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值