说在前面
刷博弈……
题目
题目大意
公平组合游戏
给出
n
n
堆石子,每堆石子初始都只有一个
可以合并两堆石子,得到一堆石子,石子个数等于原来两堆石子数之和
对于双方玩家,唯一允许的操作是:将两堆石子合并,且合并之后石子个数不能超过
询问是否先手必胜
范围:
n,m≤109
n
,
m
≤
10
9
数据组数:
T≤10
T
≤
10
输入输出格式
输入格式:
第一行一个整数
T
T
,表示数据组数
接下来 行,每行两个整数
n,m
n
,
m
,含义如题
输出格式:
对于每组数据,输出一行:
如果先手必胜输出
0
0
,不然输出
解法
(感觉比较神的一道题,看了lych的题解,这里只是整理思路)
首先可以确定,只有最终的合并次数,对答案有影响
偶数次先手必败,奇数次先手必胜
那么对于任意一个初始局面,先手都希望合并奇数次,而后手都希望合并偶数次
结论是,双方一定都可以达到合并次数最多的局面
合并次数最多的情况,显然就是石子堆都变成了这样:
m,m,⋯,nmodm
m
,
m
,
⋯
,
n
mod
m
证明:假设这样的合并次数是偶数,那么后手一定可以达到这个局面
- 首先如果 n≤m n ≤ m 那么显然只能是这个局面
- 考虑现在石子个数是
m+1
m
+
1
(此时
m
m
为奇数,偶数情况类似),首先先手肯定会合并两个石子,称这一堆为「大堆」,然后后手会将一堆石子合并到「大堆」里。
接下来,如果先手合并了两个石子,后手就把这两个石子和最大的一堆合并。不然的话他们都会将石子向「大堆」合并。每次后手操作之后,大堆总是奇数个,所以到达 局面时,后手胜
同理,对于后手,可以推广到
(m,3)
(
m
,
3
)
局面,
(m,5)
(
m
,
5
)
局面
对于先手,也可以用类似的证明。比如对于
m+2
m
+
2
颗石子,先手始终将石子向大堆合并,最后一步要么是
(m,1,1)
(
m
,
1
,
1
)
,要么是
(m−1,2,1)
(
m
−
1
,
2
,
1
)
,然后可以得出先手必胜
然后也可以推广到
m,m,m⋯
m
,
m
,
m
⋯
的局面
于是这题就做完了
下面是代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int T ;
long long N , M ;
int main(){
scanf( "%d" , &T ) ;
while( T -- ){
scanf( "%lld%lld" , &N , &M ) ;
long long t = ( N / M ) * ( M - 1 ) + ( N %M ? N %M - 1 : 0 ) ;
if( t&1 ) puts( "0" ) ;
else puts( "1" ) ;
}
}