poj3480 反NIM游戏

来源:互联网 发布:洛克希德马丁公司知乎 编辑:程序博客网 时间:2024/06/08 09:58

参考资料:
http://www.cnblogs.com/rainydays/archive/2011/07/15/2107018.html

题意:

操作过程和NIM一样,只是最后取完石子的人失败。

结论:

必胜态为:
1.所有的都是1,异或结果为0。。。。1状态
2.有大于1的,异或结果不为0。。。。2状态

必败态为:
1.所有的都是1,异或结果不为0。。。。3状态
2.有大于1的,异或结果为0。。。。。。4状态

证明:

证明的思路大致如下:
证明1能转移至3, 2能转移至4。结论得证。

为什么这样就算证好了?

根据定义,证明一种判断position的性质的方法的正确性,只需证明三个命题:
1、这个判断将所有terminal position判为P-position;
2、根据这个判断被判为N-position的局面一定可以移动到某个P-position;
3、根据这个判断被判为P-position的局面无法移动到某个P-position。 (有点归纳的意思)

以下是证明过程:

对应命题1的证明:

最终必败态为只有1个,就是只有1个石子,符合。

对应命题2的证明:

1、状态1可以转移至状态3。

这个在参考资料中被称为“易得”,我在这里感性理解一下:
状态1即为有偶数堆,每堆个数为1;状态3为有奇数堆,每堆个数为1。那么这样易得状态1为必胜态(N-position),状态3为必败态(P-position)

2、状态2可以转移至状态4。

对于2状态:假设异或结果为x。

1>当x=1时,
最低位为1的堆有奇数个。只要在这些最低位为1的堆中选择一个取走1个石子,就可将最低位为1的堆数变为偶数,异或结果变为0。
其中一个最低位1的操作,并不会让任何一个大于1的堆消失。因为堆数由奇变偶,最小的情况也是3->2。因此不会导致状态1。
又已知先前的异或结果为1,此时的异或结果变为0,不会导致状态3,而会变为状态4。

2>当x>1时:
对于2状态:

假设异或结果为x。

当x=1时,肯定是最低位为1的堆有奇数个,只要在这些最低位为1的堆中选择一个取走1个石子,就可将最低位为1的堆数变为偶数,抑或结果变为0。其中一个最低位1的操作,并不会让任何一个大于1的堆消失。因此不会导致状态1。抑或结果为0,不会导致状态3,而会变为状态4。

当x>1时:(好吧这一段太长了今天时间紧我承认我没有看完)
{
x与一个在x最高位是1且其余位均为0的数(设导致最高位为1的堆为a)异或后结果设为y,即y是将x的最高位由1改为0后得到的数字。
y=0时
{
其它的堆全为1个石子时,将a堆减为1,满足3状态。
如果其它堆中有大于石子数1的,将a堆取走若干,使得的a堆最高位变为0其他位不变,就满足4状态了。
}
y=1时
{
其它的堆全为1个石子时,将a堆取走若干,使得的a堆最高位变为0其他位不变,满足3状态。
如果其它堆中有石子数大于1的,将a堆取走若干,使得的a堆最高位变为0并使得最低位为1,其他位不变,就满足4状态了
}
y>1时,就将a堆的最高位减少使得其余位恰好与y相同(这是可以做到的,因为a堆最高位为1的数,大于y),使得抑或结果为0,满足4状态。
}

对于4状态,它不能变为另一个异或结果为0的(不能变为4状态)。而且异或结果为0就不可能只有一个大于1的堆,所以也不能变为3状态.所以只能变为必胜态。
所以它也满足。
对于4状态,它不能变为另一个异或结果为0的(不能变为4状态)。而且异或结果为0就不可能只有一个大于1的堆,所以也不能变为3状态.所以只能变为必胜态。
所以它也满足。

因此得证。

代码很简短:

#include<cstdio>using namespace std;int a[50];int main(){    int T;    scanf("%d",&T);    while(T--){        int n;        scanf("%d",&n);        int XOR=0,sg=1;        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            XOR^=a[i];            if(a[i]!=1) sg=0;        }        if(sg){            if(!XOR) printf("John\n");//先手必胜             else printf("Brother\n");//先手必败         }        else{            if(XOR) printf("John\n");            else printf("Brother\n");        }    }       return 0;}

怎么得出这个结论的?我也不知道,能做的也只有已知结论去证明过程了……以及这应该是我刷的最后一道博弈论题了,还没完成的学习笔记和未贴上来的题会慢慢完善,博弈论的复习也算告一段落

原创粉丝点击