把和尚两两配对,如 1,2 配对; 3,4 配对。每对和尚之间相隔多少个台阶就是多少个石子,配对的一对和尚就是一个石子堆。那么我们就把原题目转化为了 Nim 游戏。
如果是共有奇数个和尚,那么落单的那个可以认为是数量为 0 的石子堆。
每次取石子 x 个,等效于将配对的第一个和尚(即第奇数个)向前移动 x 步。
两两配对的正确性证明:
如果移动随便一个和尚 p 步,那么下一个人可以跟随着移动它的上一个和尚 p 步,不断这么操作。这样的情况递归下去就是,假设移动第 i 个和尚 p 步,那么接下来 i 步会使得前 i 个和尚都往前移动了 p 步。当 i 是偶数时,可以保证在局面(先后手次序)不变的情况下,使得整体往右平移,最终使得第偶数个和尚与下一个和尚的距离都等价变成 0 。即所有第偶数个和尚都无法移动为止。此时只有第奇数个和尚是能够移动的。
对共有奇数个和尚时,因为最后一个和尚的位置按照题意本来就是最高级台阶,他本来就是不能移动的,不用管他即可。
因此,转化后,根据 Nim 游戏规律,异或和为 0 先手必败,否则先手必胜。
因为数据量很小,我们可以暴力枚举所有第一步移动状态,枚举所有的将第 i 个和尚移动 j 步,重新计算间隔,然后看看这么做之后新的 Nim 游戏石子堆异或和是不是为 0 ,是的话走完先手必败,即没走先手必胜。
#include <bits/stdc++.h>
using namespace std;
#define mn 102
int m[mn],n,v,s[mn],sum;
signed main()
{
while(scanf("%d",&v)!=EOF) m[++n]=v;
for(int i=1;i<n;++i) s[i]=m[i+1]-m[i]-1;
for(int i=1;i<n;i+=2) sum^=s[i];
if(sum==0) return printf("-1")&0;
for(int i=1;i<n;++i) for(int j=1;m[i]+j<m[i+1];++j)
{
s[i]-=j;//将第i个和尚走j步
if(i!=1) s[i-1]+=j;//对应影响
sum=0;
for(int k=1;k<n;k+=2) sum^=s[k];
if(sum==0) return printf("%d %d",m[i],m[i]+j)&0;
s[i]+=j;//回溯
if(i!=-1) s[i-1]-=j;
}
return 0;//程序代码不可能走到这里
}