尼姆博弈:有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
这种情况与二进制有着很大的关系,我们用(a,b,c)来表示某种局势,那么(0,0,0)必然为奇异局势,最后一个面对这个局势的必败。(0,n,n)也是种奇异局势。因为如果对手在其中一堆取m个石子(m<=n),那么你也可以在另外一堆中取m个,他取几个你就取几个,到最后有一堆变为0的时候,你再取完另一堆胜利。
直接说结论吧:
对于任意的奇异局势(a,b,c),都有a^b^c=0。(^为异或运算)。
对于任意的非奇异局势(a,b,c),假设a<b<c,将它变为奇异局势的方法是:将c变成a^b。
原理:因为a^a=0,所以a^b^c=a^b^(a^b)=(a^a)^(b^b)=0,所以只需将c-(a^b)即可。
例1:有个非奇异局势(14,21,39),因为14^21=27,39-27=12,所以从39中拿走12个物体即可达到奇异局势(14,21,27)。
例2:我们来实际进行一盘比赛看看:
甲:(7,8,9)->(1,8,9)奇异局势
乙:(1,8,9)->(1,8,4)
甲:(1,8,4)->(1,5,4)奇异局势
乙:(1,5,4)->(1,4,4)
甲:(1,4,4)->(0,4,4)奇异局势
乙:(0,4,4)->(0,4,2)
甲:(0.4,2)->(0,2,2)奇异局势
乙:(0,2,2)->(0,2,1)
甲:(0,2,1)->(0,1,1)奇异局势
乙:(0,1,1)->(0,1,0)
甲:(0,1,0)->(0,0,0)奇异局势
甲胜。
性质1:对于某个局面(a1,a2,...,an),若a1^a2^...^an!=0,一定存在某个合法的移动,将ai改变成ai'后满足a1^a2^...^ai'^...^an=0。
分析:令res=a1^a2^......an,设res的最高位为pos(那pos的数肯定为1啦),那么一定存在某个ai,它的二进制在pos位上也是1,(否则k的最高位那个1是怎么得到的)。异或res后这位变为0,这时ai^res<ai一定成立。则我们可以将ai改变成ai'=ai^res,此时a1^a2^...^ai'^...^an=a1^a2^...^an^res=0。
性质2:对于某个局面(a1,a2,...,an),若a1^a2^...^an=0,一定不存在某个合法的移动,将ai改变成ai'后仍满足a1^a2^...^ai'^...^an=0。
例题1:POJ 2975,题目意思是给你一组局势,问有多少中必胜的策略。
分析:求出res=a[0]^a[1]^a[2].....a[n-1],由于每次只能改变一堆石子的数量,由性质1,可知如果res!=0,那么一定存在某个合法的操作,使得res=0,只要满足a[i]*res<=a[i]。
#include<iostream> using namespace std; const int MAX=1010; int a[MAX]; int main() { int n,res; while(cin>>n,n) { int count=0; for(int i=0;i<n;i++) cin>>a[i]; res=a[0]; for(int i=1;i<n;i++) res^=a[i]; if(res==0) cout<<0<<endl; else { for(int i=0;i<n;i++) if((a[i]^res)<a[i]) count++; //要注意^和<=的优先级,必须加括号 cout<<count<<endl; } } return 0; }
SG函数:定义mex运算为最小不属于这个集合的非负整数。mex{0,1,2,4}=3,mex{}=0。
对于一个给定的有向无环图,我们定义关于图的每个顶点的SG函数g如下:g(x)=mex{g(y) | y是x的后继}。
SG函数的性质:由于是一个有向无环图,那么对于所有的末端位置,由于没有后继,所以SG=0。另外对于一个g(x)=0的顶点x,它的所有后继y都满足g(y)!=0(由于集合中的元素是不可以重复的,所以后面的g(y)!=0)。对于一个g(x)!=0的顶点,必定存在一个后继y满足g(y)=0(这个时候最小的非负整数一定是0)。
由上可知:顶点x所代表的位置是必败点条件是:g(x)=0。
看到一个经典的话额,就贴在这里吧: