题目大意
题目链接
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
思路分析
各种博弈基础
一个半月,以一道博弈题poj 破百!继续努力
首先我们规定: 后手必胜态被称为奇异局势,(0,0)
想一下(0,0)的下一个奇异局势是什么?
(2,1)
如果先手取走“1”中的1个,那么后手就从“2”中取出2个,此时取完,所以后手胜利。
如果先手取走“2”中的2个,那么后手取走“1”中的1个,此时取完,后手胜利。
如果先手取走“2”中的1个,那么后手就在两堆中各取走1个,此时取完,后手胜利。
如果先手在“1”和“2”各取走了1个,那么后手取走“2”中的1个,此时取完,后手胜利。
再下来是什么?
0: (0,0)
1: (1,2)
2: (3,5)
3: (4,7)
4: (6,10)
5: (8,13)
我们发现,第i个奇异局势的差值是i
我们发现,每一个状态的第一个都是以前没有出现过的最小非法整数。
证明:
假设第k个局势为(x, k + x)
如果先手缩小差值,后手可以变成先前的局势,然后死了,所以先手不会着么做。
如果x是之前已经出现过的数, 那么先手肯定可以缩小,取到与x匹配的奇异局势,后手死了。
如果x比mex大,可以两堆缩小成x = mex,然后后手又死了。
所以当且仅当x = mex时(x, k + x)为奇异局势。
显然地,全体正整数被奇异局势分割成两个不相交的集合。
乱搞之中,我们想到了beatty定理。
我们发现,相邻奇异局势的第一个数的差值是1或2,但分布过于玄学,所以我们可以认为第一个数被表示成
,n为任意正整数,a为一无理数。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
using namespace std;
int n, m;
const double lorry = (sqrt(5.0) + 1.0) / 2.0;
int main() {
while (cin >> n >> m) {
if (n < m) swap(n, m);
int a = n - m;
if (m == int(lorry * (double)a))
cout << 0 << endl;
else
cout << 1 << endl;
}
}