题目地址:
https://www.luogu.com.cn/problem/P2252
题目描述:
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
输入格式:
输入共一行。
第一行共两个数
a
,
b
a, b
a,b,表示石子的初始情况。
输出格式:
输出共一行。
第一行为一个数字
1
1
1、
0
0
0或
−
1
-1
−1,如果最后你是胜利者则为
1
1
1;若失败则为
0
0
0;若结果无法确定则为
−
1
-1
−1。
数据范围:
50
%
50\%
50%的数据,
a
,
b
≤
1000
a, b\le 1000
a,b≤1000
100
%
100\%
100%的数据,
a
,
b
≤
1000000000
a, b \le 1 000 000 000
a,b≤1000000000
设
(
a
,
b
)
(a,b)
(a,b)为两堆石子的个数,考虑所有的先手必败态,简称“奇异态”,先证明一些结论:
1、
(
a
,
b
)
(a,b)
(a,b)是奇异态,则
a
≠
b
a\ne b
a=b,且
(
b
,
a
)
(b,a)
(b,a)也是奇异态。这个结论显然。所以我们接下来只需要考虑
a
<
b
a<b
a<b的情形;
2、固定
a
a
a,奇异态是唯一的。这一点也显然,如果
(
a
,
b
1
)
,
(
a
,
b
2
)
(a,b_1),(a,b_2)
(a,b1),(a,b2)都是奇异态,且
b
1
>
b
2
b_1>b_2
b1>b2,则先手可以从
b
1
b_1
b1中拿走
b
1
−
b
2
b_1-b_2
b1−b2个石子,此时得到了另一个奇异态,从而
(
a
,
b
1
)
(a,b_1)
(a,b1)是必胜态,矛盾;
3、考虑前若干个奇异态(即将所有满足
a
<
b
a<b
a<b的奇异态按照
a
a
a从小到大排序),它们是
(
1
,
2
)
,
(
3
,
5
)
,
(
4
,
7
)
,
(
6
,
10
)
,
.
.
.
(1,2),(3,5),(4,7),(6,10),...
(1,2),(3,5),(4,7),(6,10),...,可以发现,第
k
k
k个奇异态的第一个数
a
k
a_k
ak等于第
1
∼
k
−
1
1\sim k-1
1∼k−1的奇异态中未出现的最小正整数,且
b
k
=
a
k
+
k
b_k=a_k+k
bk=ak+k。结论是,奇异态的通项公式为
(
⌊
n
ϕ
⌋
,
⌊
n
(
ϕ
+
1
)
⌋
)
,
ϕ
=
5
+
1
2
(\lfloor n\phi \rfloor,\lfloor n(\phi+1)\rfloor),\phi=\frac{\sqrt 5+1}{2}
(⌊nϕ⌋,⌊n(ϕ+1)⌋),ϕ=25+1。
证明:首先介绍Beatty定理,这个定理说,若两个无理数
α
,
β
\alpha,\beta
α,β满足
1
α
+
1
β
=
1
\frac{1}{\alpha}+\frac{1}{\beta}=1
α1+β1=1,则
A
=
{
⌊
n
α
⌋
}
,
B
=
{
⌊
n
β
⌋
}
A=\{\lfloor n\alpha \rfloor\},B=\{\lfloor n\beta \rfloor\}
A={⌊nα⌋},B={⌊nβ⌋}是
N
+
\mathbb{N}^+
N+的一个划分。那么由于
1
ϕ
+
1
ϕ
+
1
=
1
\frac{1}{\phi}+\frac{1}{\phi+1}=1
ϕ1+ϕ+11=1,所以通项公式的每一个数取遍
N
+
\mathbb{N}^+
N+。
下面证明, 通项公式的两个不同状态之间不能一步到达。首先
⌊
n
(
ϕ
+
1
)
⌋
−
⌊
n
ϕ
⌋
=
n
\lfloor n(\phi+1)\rfloor-\lfloor n\phi\rfloor=n
⌊n(ϕ+1)⌋−⌊nϕ⌋=n彼此不同,所以不能通过第二种取法到达;第一种取法会使得两个坐标中的一个不变,从而也不行。所以两个通项公式的状态之间不能互相到达;
取一个通项公式之外的某个状态
(
x
,
y
)
(x,y)
(x,y),由通项公式的每一个数取遍
N
+
\mathbb{N}^+
N+知道必然存在某个通项公式中的项
(
a
,
b
)
(a,b)
(a,b)使得
a
=
x
∨
b
=
y
a=x\lor b=y
a=x∨b=y,那么状态
(
x
,
y
)
(x,y)
(x,y)可以一步到达
(
a
,
b
)
(a,b)
(a,b)。
所以证明了通项公式中的项之间不能互相到达,并且之外的项必然可以一步到达公式中的某一项,从而公式中的状态都是奇异态。
回到题目,如何判断 ( a , b ) (a,b) (a,b)是不是奇异态呢?不妨设 a < b a<b a<b,那么 ∃ n , ( a , b ) = ( ⌊ n ϕ ⌋ , ⌊ n ( ϕ + 1 ) ⌋ ) , ϕ = 5 + 1 2 \exists n, (a,b)=(\lfloor n\phi \rfloor,\lfloor n(\phi+1)\rfloor),\phi=\frac{\sqrt 5+1}{2} ∃n,(a,b)=(⌊nϕ⌋,⌊n(ϕ+1)⌋),ϕ=25+1,则 b − a = n b-a=n b−a=n。接下来只需要判断 a = ⌊ n ϕ ⌋ a=\lfloor n\phi\rfloor a=⌊nϕ⌋是否成立即可,如果成立,则先手必败,否则必胜。代码如下:
#include <iostream>
#include <cmath>
using namespace std;
int n, m;
const double phi = (sqrt(5.0) + 1.0) / 2.0;
int main() {
scanf("%d%d", &n, &m);
if (n > m) swap(n, m);
printf("%d\n", n == int(phi * (double)(m - n)) ? 0 : 1);
}
时空复杂度 O ( 1 ) O(1) O(1)。