典型的裸的nim游戏
看过与博弈论有关的文章都知道nim游戏有个结论:
有n堆石头,两个人轮流从这n堆中一堆石头去取出任意数目的石头,最后取光石头者得胜
设第i堆石头ai个石头 ,则 若a1^a2^a3^..^an=0,则先手去石头的人输,反之则赢。
(我只是知道这个结论,不会证明,,暑假的时候看别人的证明看了好久 最后还是是懂非懂! ⊙﹏⊙‖∣)
这题意思是有 n个采石场第i个采石场有mi堆石头,其中第j堆石头的数目为xi+j-1;
设ans为所有堆的石头的数目的异或总和
首先看到这题我没仔细看这题的数据范围,然后我直接把所有的数一个一个枚举出来,异或等到最后结果,
for(int i=1; i<= n; i++)
for(int j=0; j< m[i]; j++)
{
ans^=(x[i]+ j);
}
等到TLE的才发现一个一个数去异或是不行滴
这时我们可以可以利偶数异或偶数加一的值等于一 去优化计算
最终代码如下:
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<limits.h> using namespace std; __int64 m[111111],x[111111]; int f(__int64 a,__int64 b) { __int64 ans=0; if(a%2!=0) { ans^= a; a++; b--; } while(b%4!=0) { ans^= (a+b-1); b--; } return ans; } int main() { int n; while(scanf("%d",&n)!=EOF) { __int64 ans=0; for(int i=1; i<= n; i++) scanf("%I64d %I64d",&x[i],&m[i]); for(int i=1; i<= n; i++) { ans^=f(x[i],m[i]); } if(ans) printf("tolik\n"); else printf("bolik\n"); } return 0; }