poj1067--取石子游戏--(神奇的黄金分割比)

Description

有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。

Input

输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,000。

Output

输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0。

Sample Input

2 1

8 4

4 7

Sample Output

0

1

0

题解:

  (一道好题,主要结合了lyh学长的课件和一篇博客: http://www.cppblog.com/coreBugZJ/archive/2012/06/04/177481.html ,加深了一下理解)

  (以下的必胜态与必败态都站在先手的立场来说)

  1.如果当前a==b,显然为必胜态,直接取走两堆所有石子;

  2.如果当前(a,b)为必败态,那么(a+d,b+d)为必胜态,我们可以第一次就取走两堆中各d个石子,把必败态扔给对方(d>0);

  3.在所有的核(必败态)中,每个数字出现且仅出现一次(好像没什么可说的);

  4.如果当前(a,b)为必败态,那么(a,x)和(y,b)都是必胜态

    证明:(1).当x>m时,可以从第二堆中拿走x-m个,把(a,b)这种必败态扔给对方(当(y,b)时同理);

    (2).当y<n时,假设我们学过一个内容为“必败态的前继都是必胜态”的定理。我们可以假设(y,b)是必败态,那么假设给它补上a-y个石子来试图反证。即(y,b)的前继(a,b)是个必胜态,当前结果与我们的前提条件矛盾,故不成立。

  5.当a(i)=mex{a(J),b(J)}(0<J<i)时,b(i)=a(i)+i是核(必败态);

  (偷学长的证明过程……跑路跑路~)  

  证明:由数学归纳法证明
  • 首先当i==1的时候,(1,2)显然。
  • 下面我们假设(1~i-1)都成立,证明第i个成立。
  • 同定理三的构造方法构造出非核节点(a(i),b(J)-a(J)+a(i)),其中J<i,由本命题假设b(J)-a(J)==J,这样我们构造的i-1个非核节点b-a是从1~i-1在Z上连续递增的,那么没有出现的第一个节点即为核节点,此时没有出现的节点是(a(i),a(i)+i);

  6.神奇地发现必胜态在坐标系上表示的话,趋近于一条直线,斜率为黄金分割比……

  真的好神奇啊,不会证……
  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 const double gold=(sqrt(5.0)+1)/2;
 6 int main()
 7 {
 8     int a,b,d;
 9     while(scanf("%d%d",&a,&b)!=EOF)
10     { 
11         if(a>b)swap(a,b);
12         if((int)(abs(a-b)*gold)==a)
13             cout<<0<<endl;
14         else
15             cout<<1<<endl;
16     }
17     return 0;
18 }
View Code

 


  

posted @ 2017-08-21 21:25  BK-Edwina  阅读(275)  评论(0编辑  收藏  举报