取石子游戏
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3760 Accepted Submission(s): 1892
2 1 8 4 4 7
0 1 0
威佐夫博奕(Wythoff Game):
有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜.
(ak,bk)(ak ≤ bk ,k=0,1,2,...,n)表示奇异局势
一定存在规则允许的某种操作可将必胜点(非奇异)移动到必败点(奇异);
求法:
ak =[k(1+√5)/2], bk= ak + k (k=0,1,2,...,n 方括号表示取整函数)
判断:
Gold=(1+sqrt(5.0))/2.0;
1)假设(a,b)为第k种奇异局势(k=0,1,2...) 那么k=b-a;
2)判断其a==(int)(k*Gold),相等则为奇异局势
局势(Ak,Bk) 奇异局势特征:Ak =[k(1+√5)/2],Bk= Ak + k (k=0,1,2,...n 方括号表示取整函数)
结论:Bk - Ak = k; if(Ak == [k * (1 +
√5
) / 2]) ->奇异局势。(注:采用适当的方法,可以将非奇异局势变为奇异局势.
假设面对的局势是(a,b) 若 b = a,则同时从两堆中取走 a 个物体,就变为了奇异局势(0,0);
1. 如果a = ak,
1.1 b > bk, 那么,取走b - bk个物体,即变为奇异局势(ak, bk);
1.2 b < bk 则同时从两堆中拿走 ak – a[b – ak]个物体,变为奇异局势( a[b – ak] , a[b – ak]+ b - ak);
2 如果a = bk ,
2.1 b > ak ,则从第二堆中拿走多余的数量b – ak
2.2 b < ak ,则 若b = aj (j < k) 从第一堆中拿走多余的数量a– bj; (a > bj)
若b = bj (j < k) 从第一堆中拿走多余的数量a– aj; ( a > aj)
)
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define M ((sqrt(5.0)-1.0)/2.0)
#define W ((sqrt(5.0)+1.0)/2.0)
void swap(int &x,int &y)//位操作交换函数值的函数
{
x^=y;
y^=x;
x^=y;
}
int main()
{
int a,b;
while(~scanf("%d%d",&a,&b))
{
__int64 j,aj,ak;
if(a>b)
swap(a,b);
j=(__int64)a*M;
aj=(__int64)(j*W);
ak=(__int64)(W*(j+1));
if((aj==a&&b==a+j)||(ak==a&&b==a+(j+1)))
printf("0\n");
else
printf("1\n");
}
return 0;
}