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