【SHTSC 2002】取石子游戏
【题目】
题目描述:
样例数据:
【样例 】
输入
6 10
输出
0
【样例 】
输入
2 1
8 4
4 7
输出
0
1
0
【分析】
博弈论好题。
以下内容部分摘自这里。
定义 为第一堆石子有 个,第二堆石子有 个时的状态。
不妨令 ,那么显然:
- 若 是必败态,那么 都是必胜态。
- 对于每个必败态的 不会在另一个必败态中出现(由 可得出)。
- 如果有一个必败态 ,那么 为必胜态。
我们打表,发现:
任意非 自然数 一定在一个必败态中出现。且第 个必败态的形式为 。
是满足不在以前必败态中的任何一个数出现的最小非 自然数(由 可得出)。
证明:
对于 ,假设其为必胜态,那么必然存在一种操作使其转换为必败态。
首先假设我们在 中拿出一些石子,使 减小到 ,即转换为 ,那么 一定在前面的必败态出现过。由于 严格单调增,不属于前面任何一项的 。此时得到的局面为必胜态(由 可得出)。所以不能减小 。
其次若 减小,得到 ,易得到 ,显然这是一个必胜态(由 可得出)。所以不能减小 。
然后也不可能两项同时减小得到必败态,因为前面的必败态的差都小于 。
所以用反证法,这个结论是对的。
这个时候,我们就需要一个神奇的东西叫贝蒂定理来完成后面的步骤了。
先摘抄一下贝蒂定理的内容。
设 是无理数且 ,我们记 。
那么 为空集且 为正整数集合 。
证明的话就自己去百度看吧。
有了这个定理,我们就可以通过构造合适的 来求出第 个必败态。
那我们令 ,即 ,这样的话, 中第 个元素刚好比 中第 个元素大了 ,就可以满足我们的要求。
这样解出来,发现 ,刚好也是一个无理数,满足前提。
因此,对于一个状态 ,如果 ,那就是必败态,否则是必胜态。
【代码】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n,m;
double temp=(sqrt(5)+1)/2;
while(~scanf("%d%d",&n,&m))
{
if(n>m) swap(n,m);
puts(n==(int)(temp*(m-n))?"0":"1");
}
return 0;
}