取石子游戏
                     

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. PHP文件的上传与下载

    文件上传: 1.单个与多个文件上传 2.上传表单的属性设置 3.PHP配置文件中相关文件上传的设置 4.PHP处理上传的文件数据 php.ini配置: file_uploads = on; 默认on ...

  2. Hanoi问题

    #include<stdio.h>int main(){ int m; void hanoi(int n,char x,char y,char z); printf("input ...

  3. Mac Mini中添加VNC访问

    开启Mac Mini上面的VNC. 1) 打开“系统偏好设置”(System Preference),双击打开“共享”(Sharing)项. 2)在左侧将“屏幕共享”(Screen sharing) ...

  4. canvas对象arcTo函数的使用-遁地龙卷风

    (-1)环境说明 我使用的浏览器是chrome49 (1)详细介绍 $(function() { var context = lol.getContext("2d"); conte ...

  5. EasyUI中Dialog的使用

    $(function () { $('<div id="dlgContent"></div>').appendTo($('body')); $('#dlgC ...

  6. cocos2dx中CC_CALLBACK_1等宏中this指针实际指向

    首先看代码,我在Helloworld中添加两个函数. void HelloWorld::addTarget(){ Size visibleSize = Director::getInstance()- ...

  7. iOS开发——高级篇——UIDynamic 物理引擎

    一.UIDynamic 1.简介什么是UIDynamicUIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象重力.弹性碰撞 ...

  8. junk

    var mydate1 = new Date($('.stt').html()); var mydate2 = new Date($('.ett').html()); if (window.Activ ...

  9. Android学习笔记(二)——探究一个活动

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 活动(Activity)是最容易吸引到用户的地方了,它是一种可以包含用户界面的组件,主要用于和用户进行交互.一 ...

  10. [BZOJ1691][Usaco2007 Dec]挑剔的美食家

    [BZOJ1691][Usaco2007 Dec]挑剔的美食家 试题描述 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了. ...