威佐夫博奕(Wythoff Game)
定义:有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
思考:
把两堆石子的集合写为(a,b)不失一般性令我们只考虑a<=b的情况;
我们依次考虑(0,0)-(0,*)……(n,n)-(n,*)的情况。把所有状态看成一个二维数组,我们只需考虑上三角的情况;
(0,0)必败点,故(0,*)为必胜点;(1,1)一步可以取完,故也为必胜点;
(1,2)无论怎样取都只能到达必胜点,所以(1,2)为必败点;
(1,*)(2,*)可一步到达(1,2),故其都为必胜点;
此时我们发现一些规律,只有一些特殊的点是必败点,其余大多数情况为必胜点,再次我们不妨称必败点为“奇异局势”,这个定义我们在以后的学习中还可用到;
当(0,*)(1,*)(2,*)都考虑完后,开始考虑(3,*);(3,3)显然可一次取完为必胜点,(3,4)可以减(2,2)到达(1,2),所以也为必胜点;这里我们可以看到一个特点,如果a,b之差等于上述所提到“奇异局势”两堆石子之差时,则(a,b)-(m,m)是可以到达上述情况的,所以凡是后面要找到的点a,b,之差不能等于前面所找到的奇异局势;这时我们发现(3,5)为奇异局势;同理,(3,*)和(5,*)都为必胜点了,和上次推导一样(4,4)(4,5)(4,6)都为必胜点(4,7)为我们要找的奇异局势;(4,*)(7,*)必胜;(6,*)这一行还会有一个奇异局势,我们找到它是(6,10),相差为4;
此时,我们一经发现了一个规律,第i个奇异局势a,b之差为i,如果字典顺序寻找,则(a,b)中的a,为之前奇异局势中未出现的最小的自然数;写到这,你或许可以编程解决一些这样的问题了吧,但这貌似还是有点麻烦,没关系,数学家已经给出了我们a的通项公式(如要了解推导过程可自行查阅资料,这里不作为重点讨论),即ai=[i*(1+√5)/2](方括表示下取整),bi=ai+i,。
=======================================================================
搜到的题解,是懂非懂,上个代码吧!
#include <stdio.h> #include <string.h> #include <math.h> int main() { int n,m,t,K; double a; while(scanf("%d%d",&n,&m)!=EOF) { if(n>m) { t=n; n=m; m=t; } K=m-n; if(((int)(K*(sqrt(5.0)+1.0)/2.0))==n) printf("0 "); else printf("1 ");//printf("%d",K*(sqrt(5.0)+1.0)/2.0); } return 0; }