【洛谷】P2252 取石子游戏|【模板】威佐夫博弈(配数学证明)

题目地址:

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,b1000
100 % 100\% 100%的数据, a , b ≤ 1000000000 a, b \le 1 000 000 000 a,b1000000000

( 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 b1b2个石子,此时得到了另一个奇异态,从而 ( 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 1k1的奇异态中未出现的最小正整数,且 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=xb=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 ba=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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值