题意:有n个沙场,每个沙场有m个车子,每个车子里装的石子个是从第一车子里依次递增的。他们两相互取石子,问是先取赢还是后取赢。
这题是裸的Nim游戏,ans=s1^s2......s3.s代表每一堆石子的个数。
这题最主要不在于Nim游戏的结论,而是怎样在连续的自然数中快速求出前m个数的异或,这是基于一些理论:【(N^0=N),(1^1=0,1^0=1,0^0=0),(N^(N+1)=1,N为偶数),异或满足交换律】,结合数学分类可以快速求出。
#include<iostream>
#include<cstdio>
#include<cstring>
typedef __int64 LL;
using namespace std ;
LL get(LL x,LL y) //基于n^(n+1)=1,n为偶数。
{
LL ans;
if(y&1){ //有奇数个
if(x&1) ans=x; //取x后面的数。
else ans=x+y-1; //取x+y-1前面的数。
y--;
}
else{
if(x&1) ans=x^(x+y-1),y-=2; //可以求出中间的,取两头。
else ans=0;
}
return y%4==0? ans:ans^1; //判断是否为偶数对
}
int main()
{
int n;
LL x,m,ans=0;
scanf("%d",&n);
while(n--){
scanf("%I64d %I64d",&x,&m);
ans^=get(x,m);
}
printf(ans?"tolik\n":"bolik\n");
return 0 ;
}