题目大意:
就是Wythoff Game的原型, 每次可以拿其中一堆的任意数量或者两堆同时拿一样的任意数量, 拿走最后一颗石子的人胜
大致思路:
首先可以参考这篇Wythoff Game的论文:
Wythoff Game
其中提到了一个Beatty Theorem(贝蒂定理):
如果
a
和
另外Wythoff Game当中一个重要的表:
The Sequence of Safe Pairs (A, B)
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | … |
---|---|---|---|---|---|---|---|---|---|---|---|---|
A | 0 | 1 | 3 | 4 | 6 | 8 | 9 | 11 | 12 | 14 | 16 | … |
B | 0 | 2 | 5 | 7 | 10 | 13 | 15 | 18 | 20 | 23 | 26 | … |
这里我们是不妨假设了
A≤B
其中
(A,B)
是
P
点的条件是
其中
ϕ
是黄金比例
ϕ=1+5√2
上表中的一些性质
将第
i
列的
对于每一个
A[k]
,
A[k]
一定是前面
(A[i],B[i])
中没有出现过的最小自然数, 并且任何一个自然数都包含在一个且仅有的一个
P
点中(也有文章称为奇异局势), 这里我们只考虑了
那么接下来说明任意操作都可以将奇异局势(
P
点)变成非奇异局势(
如果
(A[k],B[k])
是奇异局势(
P
点), 如果只改变其中一个数, 那么得到的分量不可能在其他奇异局势中(
对于一个非奇异局势(
N
点),记为
如果
a=A[k],b<B[k]
, 那么两堆同时拿走
A[k]−A[b−A[k]]
, 很明显由于
B[k]>b>a>A[k]
, 这里取走
A[k]−A[b−A[k]]
中
b−A[k]<B[k]−A[k]=k
, 所以肯定是可取的, 那么这样就变成了
(A[b−A[k]],b−A[k]+A[b−A[k]])
, 也就是
(A[b−A[k]],A[b−A[k]]+(b−A[k]))
,
B[b−A[k]]=A[b−A[k]]+(b−A[k])
所以变成了奇异局势(
P
点)
如果
如果
a<A[k],b=A[k]+k=B[k]
那么当
a=A[j]
时
(j<k)
从第二堆拿走
b−B[j]
即可
当
a=B[j]
时
(j<k)
, 从第二堆拿走
b−A[j]
即可
以上两种一定包含了所有情况, 因为之前找到的性质:
A[i]
是前面没有出现的最小自然数
以上是学习到的所有Wythoff Game相关的东西了, 这里了一下:
接下来就是代码了, 利用黄金分割来判断是否是(A[i], B[i])即可
代码如下:
Result : Accepted Memory : 1576 KB Time : 31 ms
/*
* Author: Gatevin
* Created Time: 2015/5/8 10:14:35
* File Name: Rin_Tohsaka.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define foreach(e, x) for(__typeof(x.begin()) e = x.begin(); e != x.end(); ++e)
#define SHOW_MEMORY(x) cout<<sizeof(x)/(1024*1024.)<<"MB"<<endl
const double gold_ratio1 = (1 + sqrt(5.)) / 2;
const double gold_ratio2 = (sqrt(5.) - 1) / 2;
int a, b;
int main()
{
while(scanf("%d %d", &a, &b) != EOF)
{
if(a > b) swap(a, b);
int t = floor(a*gold_ratio2);
if(floor(t*gold_ratio1) != a)
{
if(a + t + 1 == b) puts("0");
else puts("1");
}
else
{
if(a + t == b) puts("0");
else puts("1");
}
}
return 0;
}