POJ 1067 取石子游戏【威佐夫博奕】
POJ 1067 取石子游戏
大意:有两堆石子,数量为A,B.两个玩家轮流从中取石子,每次可从一堆中取若干颗或从两堆中取相同数目石子,
最后取完者为胜,问先取者是否有必胜策略?
分析:
比较裸的威佐夫博奕(Wythoff Game)
有黄金分割知,不安全局面(an,bn)满足:
an = floor(a*n),bn = floor(b*n);
其中:
a = (1+sqrt(5))/2
b = (3+sqrt(5))/2
在本题中,已知石子个数A,B,判断A,B是否能满足上述条件,即
若存在n能使得:
floor(n*a)==A,floor(n*b)==B (1)
那么便必输,否则必胜
逆推上式,若存在该n,则 n = ceil(A/a),然后再判断(1)是否成立即可。
特别注意:在n的求解中必须向上取整!
View Code
1 #include<stdio.h>
2 #include<math.h>
3 const double alpha = (1.0+sqrt(5.0))/2.0;
4 const double beta = (3.0+sqrt(5.0))/2.0;
5
6 int main()
7 {
8 __int64 a,b;
9
10 while(scanf("%I64d%I64d",&a,&b)!=EOF)
11 {
12 if(a>b)
13 {
14 __int64 temp = a;
15 a = b;
16 b=temp;
17 }
18
19 __int64 n = (ceil)(a/alpha); //必须向上取整
20 __int64 ta = (__int64)(alpha*n);//注意强制类型转换的书写格式
21 __int64 tb = (__int64)(beta*n);
22 if(ta==a&&tb==b)
23 printf("0\n");
24 else
25 printf("1\n");
26 }
27 return 0;
28 }