威佐夫定理(Wythoff Game)——重点讲证明
应用背景
有两堆石子,有两个绝顶聪明的人在玩一个游戏。每次每个人可以从其中一堆石子当中取走任意数量的石子,或者是从两堆当中同时取走相同数量的石子。无法取石子的人落败,请问,在告知两堆石子数量的情况下,这两个人当中哪一方会获胜?
简单说来,这是一个不易解答的问题,但可以通过一种通法——找规律。首先,我们需要对找的过程进行定义说明——失败态(必败的情形),以(an,bn)指代两堆石子。
显然的,(0,0)即为基础失败态——说明上家已经选走了所有石子。
(1,2 )、(3,5)、(4,7)……等等都是失败态 ,But Why?
Hold on,想一想,(1,2)无论你咋选,总归结果还是(0,0),so依次推广,其他的就可以归结到(1,2)的情形。
其次,观察到(an,bn)的差值变化,0、1、2、3、4……想到点啥没?
当然得求通项公式,不过这东西真能求么?别说,还真得行,不过得有个神奇的**Betty定理**(具体请度娘~~)
如果你懂了,那么接下来就水到渠成了。
还记得最开始对石子的表示吗?[an],[bn],一波取整,直接将Betty定理中的应用一波,注意此处的an,bn是由于有理通项无法把失败态的通项公式表示出来,所以均为无理数。
这样一来可以得到一个有趣的式子
若
记
[
a
n
]
=
a
∗
n
,
则
可
推
出
有
1
a
+
1
a
+
1
=
1
若记[an]=a*n,则可推出有\frac{1}{a} +\frac{1}{a+1} =1
若记[an]=a∗n,则可推出有a1+a+11=1
一波操作后得到
a
=
1
+
(
5
)
2
a= \frac{1+\sqrt(5)}{2}
a=21+(5)
从而得到一个必败态的判断方法了。
代码如下
#include<bits/stdc++.h>
using namespace std;
int main(void){
int a ,b;
cin>>a>>b;\\(前提确保b>a)
if(int((b-a)*(sqrt(5)+1)/2))==a)cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
参考
大神文章