POJ 1067 HDU 1527 取石子游戏(威佐夫博奕)

来源:互联网 发布:普通电视怎么连接网络 编辑:程序博客网 时间:2024/04/30 09:16

OpenJ_Bailian - 1067 也是本题

关键词:

取石子游戏、威佐夫博奕、beatty贝蒂定理、胜态负态状态转移、覆盖(分划)高斯函数、第二数学归纳法、黄金分割比例

题目:

Description

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

Input

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

Output

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

Sample Input

2 18 44 7

Sample Output

010

这个游戏叫威佐夫博奕

下面,我将如实地展示我的整个思考过程。

虽然所有的内容(除了贝蒂定理)都是自己想的,不过估计和网上写的都是差不多的。

因为我几年以前就知道了beatty贝蒂定理,现在才知道,估计这个定理就是从这个游戏衍发出来的。


首先,很容易找到,最小的负态是(1,2) (不算(0,0)的话)

(如果先手有必赢策略,那么称为胜态,否则称为负态)

定理一:(n,n)是胜态,(n,0)是负态 (n>0)

定理二:如果(a,b)和(c,d)是2个负态,那么a,b,c,d互不相等

定理三:(a,b)和(b,a)一定是完全等价的

(所以本文中只出现(3,5)这种状态不出现(5,3)这种状态(除了本行))

定理四:一个状态无法转移到任何一个负态,当且仅当它就是负态。

一个状态只要能转移到任何一个负态,那么它就是胜态

想清楚了这四点之后,可以开始找出所有负态了。(都是显然的定理,我就不证明了)


首先,(3,3)是胜态,(3,4)因为可以转移到(1,2)所以是胜态,(3,5)因为没法转移到任何一个负态,所以它就是负态。

然后,(4,4)是胜态,(4,5)和(4,6)可以转移到(3,5)所以是胜态,(4,7)是负态。

现在,有了前3个负态,(1,2)(3,5)(4,7)

光凭这3组数据是不可能发现规律的,但是如果结合刚刚找到它们的方法仔细思考,那就不一样了。

比如在找第4个负态的时候,我们发现,在(6,6)(6,7)(6,8)(6,9)......

这个序列中,如果找到1个负态的话,后面的状态都可以转移到这个状态,所以后面所有的状态都是胜态。(这其实就是定理二)

可是要怎么样知道这个序列里面有没有一个状态不能转移到前面3个负态中的任何1个呢?

请注意!如果这个序列中的某个状态不能转移到前面3个负态中的任何1个,那么它就是负态!

那么关键来了!状态转移的本质数量关系是什么?

本质数量关系就是,如果1个状态的2个数之差等于另外1个状态的2个数之差,那么它们是可以转移的!

前面3个状态的2个数之差分别是1,2,3,那么很明显,上述序列中,有且仅有1个序列是无法转移到这3个序列的,就是那个差为4的状态,即(6,10)


到了这里,可能你已经明白了,如何快速求出所有的负态。

负态的2个数之差的序列就是1,2,3,4......

如果你认为到了这里,我只是发现规律,只是猜想第i个负态的2个数之差是i,请从头再看一遍。

实际上,我们不仅已经得到了一个定理,第i个负态的2个数之差是i

我们还得到了另外1个非常重要的定理,第i个负态的较小数是集合A中的最小数,

其中A是自然数集,去掉前i-1个负态的2*(i-1)个数,得到的集合。

结合定理二可以发现,任何正整数都恰好出现在某个负态中而且仅出现1次!


当我想到这个地方的时候,我突然想起来beatty贝蒂定理

其实我对这个定理印象不深,因为从来没有用过,直到做这个题目才是第一次用。

beatty定理:对于任意满足1/a+1/b=1, 的正无理数a,b,

都有结论:[a],[2a],[3a],[4a]......[b],[2b],[3b],[4b]......都是不同的数,而且覆盖正整数集。


于是我怀疑,beatty贝蒂定理和本题有着本质的联系。

因为实在是好几年了,所以我想,还是先证明一下beatty贝蒂定理,找找感觉吧。

beatty贝蒂定理的证明:

对于任意正整数n,考虑[a],[2a],[3a],[4a]......里面有多少个数小于n

(如果考虑有多少个数小于等于n,那就得不到什么结论,因为根本算不出来,这是由高斯函数的特性决定的)

根据高斯函数的特性,[ka]<n iff ka<n 即,k<n/a (k为整数)

因为n/a是无理数,所以上式还等价于k<=[n/a]

所以说,[a],[2a],[3a],[4a]......里面有[n/a]个数小于n

同理,[b],[2b],[3b],[4b]......里面有[n/b]个数小于n

那么,一共有多少呢?

这个地方就体现了为什么要是无理数,因为n/a和n/b是无理数,那么就不是整数

又因为n/a+n/b=n,所以[n/a]+[n/b]=n-1

所以说,对于任意正整数n,[a],[2a],[3a],[4a]......[b],[2b],[3b],[4b]......中有n-1个数小于n

由此,可以利用数学归纳法推出betty贝蒂定理。

数学归纳法我就不写了,简述如下:

考虑[a],[2a],[3a],[4a]......[b],[2b],[3b],[4b]......中每个正整数有多少个

有1个数小于2,所以有1个1

有2个数小于3,所以有1个2

有3个数小于4,所以有1个3

......

就这样,利用第二数学归纳法,可以得到每个正整数都有且仅有1个。证毕□


有了贝蒂定理,(1,2)(3,5)(4,7)(6,10)。。。这各序列的通项又要怎么求呢?

还是说,这个序列根本没法用贝蒂定理来求?

我不是想死套这个定理,只是在思考,这2个东西这么像,应该是有本质联系的吧?

如果亲爱的读者是第一次知道贝蒂定理,可能感觉两者的关系并不是很密切。

那么你就需要像我初学贝蒂定理的时候一样,找几个简单的实例,比如a=sqrt(2),或者a=sqrt(3)这种简单的例子。

a=sqrt(2)时,b=sqrt(2)+2,把正整数集的划分表示成二元组就是:

(1,3)(2,6)(4,10)(5,13)(7,17)。。。。。。

差分别是2,4,6,8,10......规律和本题的几乎一样!只不过都乘了2而已

a=sqrt(3)时,b=(sqrt(3)+3)/2,把正整数集的划分表示成二元组就是:

(1,2)(3,4)(5,7)(6,9)(8,11)。。。。。。

差分别是1,1,2,3,3......这个貌似没什么规律吧?

为什么1个有规律,1个没规律呢?

看看a和b的值就一目了然了,a=sqrt(2)时,b=sqrt(2)+2,[kb]-[ka]=k*2恒成立。

现在是不是感觉这个数列和本题的数列非常像了呢?

还不够。

不管是a=sqrt(2)还是a=sqrt(3)还是其实的情况,根据贝蒂定理,都可以直接推出:

第i二元组中的较小数是集合A中的最小数,其中A是自然数集,去掉前i-1个二元组的2*(i-1)个数得到的集合。

这句话是不是很眼熟?是的,前面描述负态二元组的时候我也是这么描述的。

让我戳破最后一张纸吧。

相信聪明的读者也已经想到了,如果存在满足1/a+1/b=1, 且b=a+1,的正无理数a,b

那第i个二元组的差不就刚好是i了吗?

解这个方程可以得到,a=(sqrt(5)+1)/2,b=(sqrt(5)+3)/2


综上所述,取a=(sqrt(5)+1)/2,b=(sqrt(5)+3)/2,那么([ak],b[k])(k=1,2,3,4......)就是所有的负态。

没错,a-1=(sqrt(5)-1)/2=0.618就是黄金分割!数学就是这么美妙而神奇!

代码:

#include<iostream>#include<cmath>using namespace std;int main(){double Au = (sqrt(5) + 1) / 2;int n, m, d;while (cin >> n >> m){if (n > m)cout << (m != int((n - m)*Au)) << endl;else cout << (n != int((m - n)*Au)) << endl;}return 0;}
一时兴起,把黄金分割写成Au偷笑

全身心投入写了整整2个小时,谢谢观看。


3 0