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 }

你可能感兴趣的:(poj)