取石子游戏
                     

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 37662   Accepted: 12594

Description

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

Input

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

Output

输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0。                                        
 
 
 
 
 
 
 
 
 
2015-08-19:
 
  这道题比较有趣,代码量不多,但是里面的数学知识蕴含比较丰富。
这题就是著名的威佐夫博弈
 
  如题所言,我们要做的就是要确定谁是最后的赢家,那么这题呢,取石子的方法有很多(千万不要被采取最好的策略给骗了,不是一定要取完的意思),我们总不可能一个一个地枚举把,那样太累了,也不可取,那怎么办呢?其实,在双人博弈中,只要是把棋子下完就算获胜的那种,且满足一定规则,那么一定存在有一方一定胜的情况,这个其实是图论的知识,我们等一下再讲,不急。
 
  我们现在先观察一下,既然有一定是赢的情况,那么根据题意,我们最容易想到的就是(0,k),(k,0),(k,k)这三种情况,如果存在这三种情况,我们一定赢,那如果我们一定输的情况长什么样子的呢?我们想想,(1,2),(2,1),(3,5),(5,3)....这类的情况我们一定是输的,不信你可以试试看,我们就拿(1,2)来看,无论你把哪一边的石头取完,或者取一个之类的,你都是输。
 
  这样看,貌似这题真的难透了,因为不仅存在一定赢的情况,而且也存在一定输的情况,还存在不一定赢也不一定输的情况,那完蛋了,这题是不是没法做了呢?别急,我们这样想:
 
  如果你在必胜态上,不用想,你赢了。这种情况的前提是对手在必败态上
  如果你要保证你自己赢,首先你自己就不能在必败态,而且最好你下完以后对手一定在必败态上,这种思路可以,
  如果你不在必胜态上,你可以把自己转移到必胜态上,或者把对手逼到必败态上
 
  这样一想那么这题就好做了,我们只用找必败态就好了,关键是怎么找呢?
  带着这个疑问,我们来讲一下非常重要的模型:博弈的图论模型---必败态与核1
   TH1:胜态一定可以通过某种策略走向必败态;而必败态采取任何策略都将走向胜态。
 
   图论语言:
   TH2:因为必败态只能走向胜态,所以任何两个必败态结点之间不可能存在边;
   TH3:因为胜态总能走到必败态,所以对任何一个非必败态的结点,
      一定存在一个从它指向必败态结点的边。

   定义1:有向图中,集合X中任意两点之间无边,称集合X为内固集。
   定义2:有向图中,任意不在集合X中的点存在一条指向集合X的边,称集合X为外固集。
   定义3:有向图中,集合X 既是外固集,又是内固集,称集合X为核。

 
   TH4:双人博弈中,约定走最后一步为胜,如果有核存在,则其中一方有不败策略。
   TH5:有限个结点的无回路有向图有唯一的核。
  定理1定理2和定理3我们不证(这个根据图来理解比较好一点),
  对于定理4,因为博弈肯定对应的是有向图,我们可以假设A先走,A总是做到会把B逼入核中的情况,然后B可以退出核外(假设还是存在往外指的边),总是存在A最后会把B逼到走投无路的情况(当然你可能会问如果B退出来以后A走投无路怎么办,那不可能,因为如果是这样,A早就在核中了,违反了核的定义)。同理B也是一样分析
  对于定理5:因为图无回路,所以一定是有终点的,终点的集合即是核。
 
 
 
 
  好了知道了图论的这个知识以后,回到题目来,那么这道题,必败态就是核的集合了,那怎么找到核呢?我们可以递推的思想,找一下规律
  我们知道(0,0)是一个特殊的必败点,那么根据非必败点能走到必败点的结论,我们根据题目的条件,我们可以用3条线去掉非必败点,横线,竖线,和斜线,那么我们就去掉了(0,k),(k,0),(k,k)(k>1)的点,
  接下来我们找第一个没有划的点,他一定是一个必败点,因为这个点不可能和(0,0)有交集,符合核的定义,我们找到了(2,1)和(1,2),我们也按照上面的处理方法,划线。
  接下来就是(3,5),(5,3)这两个必败点,同理,然后就是(4,7)(7,4)………………………………一直往后推
 
  现在我们把这些点全部集中起来看,好了发现规律没?规律就是a(k)=b(k)+k,这个东西咱们写代码应该要熟悉,这个式子的a(k)和b(k)的比率,就是黄金分割率0.618(当然k要很大才是趋近这个数)
是不是有点奇怪?你可能会说,不行啊这只是我们画图推出来的规律,怎么可以拿来做结论呢?好吧,下面我们来稍微证明下:
 
  证明{(a(k),b(k))|a(k)=b(k)+k}均在核中:
反证法:  
假设存在一个{(a(k),b(k))|a(k)=b(k)+k}不在核中,那么这个点呢一定会与某一个核存在边,那么边怎么来?要么就是横着过来,竖着过来,或者斜着过来(即存在另一个节点(c(n),d(n)),使得其坐标等于c(n)=a(k)-m或者d(n)=b(k)-m或者c(n)=a(k)-m,d(n)=b(k)-m),这样想肯定不对,因为在考虑(c(n),d(n))之前,我们已经把这些边和边上的节点全部排除了,
所以,{(a(k),b(k))|a(k)=b(k)+k}均在核中。证毕
 
  另外,这个结论可以引出第二个非常著名的定理:Beatty定理2
 
  Beatty定理是个什么东西,大家可以在下面的参考资料那里看看,
我们这里只讲结论,就是威佐夫博弈的必败点坐标满足Beatty定理并且如果a(n)=[αn],b(n)=[βn],则α=(sqrt(5)-1)/2;
 
  那么接下来就是给大家看一下威佐夫博弈的代码,真的是简单的要死:
#include <stdio.h>
#include <math.h> int main(void)
{
long double p = (sqrt((long double)) + (long double)) / (long double);
int a, b, k; while (~scanf("%d%d",&a,&b))
{
k = b > a ? b - a : a - b;
a = b > a ? a : b;
if (a == (int)(p*k)) printf("0\n");
else printf("1\n");
}
}

参考资料:

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明

1.Patrick的博客--取石子游戏

(我的那个证明方法是反证,他那个是数学归纳法,更严谨一点)

2.Jack Ge的博客--取石子游戏

3.败态的过程

4.如何证明高斯取整函数和Beatty公式

5.如何证明高斯取整函数和Beatty公式

Games:取石子游戏(POJ 1067)的更多相关文章

  1. 【POJ】1067 取石子游戏(博弈论)

    Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...

  2. POJ.1067 取石子游戏 (博弈论 威佐夫博弈)

    POJ.1067 取石子游戏 (博弈论 威佐夫博弈) 题意分析 简单的威佐夫博弈 博弈论快速入门 代码总览 #include <cstdio> #include <cmath> ...

  3. poj 1067 取石子游戏 (威佐夫博弈)

    取石子游戏 http://poj.org/problem?id=1067 Time Limit: 1000MS   Memory Limit: 10000K       Description 有两堆 ...

  4. HDU 2516 取石子游戏(斐波那契博弈)

    取石子游戏 Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  5. hdu 1527 取石子游戏(Wythoff Game)

    题意:Wythoff Game 思路:Wythoff Game #include<iostream> #include<stdio.h> #include<math.h& ...

  6. HDU 2516 取石子游戏(FIB博弈)

    取石子游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  7. 1874: [BeiJing2009 WinterCamp]取石子游戏 - BZOJ

    Description小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问 ...

  8. HDU-1527 取石子游戏

    http://acm.hdu.edu.cn/showproblem.php?pid=1527 交换  :可实现. if( n < m ) { n^=m; m^=n; n^=m; } (三)尼姆博 ...

  9. bzoj 1874 取石子游戏 题解 &amp; SG函数初探

    [原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 334  Solved ...

随机推荐

  1. linux:vi 替换命令

    转自:http://www.cnblogs.com/afant/archive/2009/03/11/1408745.html :s/^.*$/\L&/100 ##将100行内的小写转换成大写 ...

  2. Lnmp的安装、配置

    一.首先在本地安装好虚拟机,在虚拟机上安装centos6.5,由于习惯问题,不喜欢直接在虚拟机上操作linux系统,习惯了ssh过去,直接用xshell操作,这完全是个人习惯问题: 1.  用xshe ...

  3. Memcached基础知识

    主要内容: Memcached基本的工作原理 Memcached的两阶段哈希 Memcached的数据存储方式 Memcached新建Item分配内存过程 Memcached的数据过期方式 Memca ...

  4. CF467D Fedor and Essay 建图DFS

      Codeforces Round #267 (Div. 2) CF#267D D - Fedor and Essay D. Fedor and Essay time limit per test ...

  5. Sublime Text3

    Sublime Text3 激活码: ----- BEGIN LICENSE ----- Andrew Weber Single User License EA7E- 813A03DD 5E4AD9E ...

  6. [译]ES6箭头函数和它的作用域

    原文来自我的前端博客: http://www.hacke2.cn/arrow-functions-and-their-scope/ 在ES6很多很棒的新特性中, 箭头函数 (或者大箭头函数)就是其中值 ...

  7. 更改vs自带的模板

    路径:C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplatesCache\CSharp\Code\20 ...

  8. 同一个解决方案"引用"其他的项目出现感叹号...

    项目A是自己新建的... 但是项目B是"添加"→"现有项目"添加的... 所以项目B引用项目A的时候,引用的项目A显示感叹号... 项目A右击"属性& ...

  9. HDU 2014

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> typedef float ElementType; void Select_Sort ...

  10. nyoj 252 01串 动态规划( java)

    当n=2时, 输出 3:当n=3时, 输出 5:当n=4时, 输出 8: #### 分析: 当n=4时,如 0101 符合条件, 当第一个位置是0时,还剩3个位置 ,与n=3时个数相等: 符合条件的为 ...