题目链接:http://acm.hit.edu.cn/problemset/1367
解题思路:这个nim游戏是谁取最后一份谁输.(0堆的时候相当于上一个人取完了最后一堆,先手必胜)
假设n堆异或和为nim
有以下状态:
①:每堆为1
--->nim=0,偶数堆 nim!=0,奇数堆 对应:
先手必胜 先手必败
②:有一堆大于1个,其余为1个
--->由堆数奇偶判断大于1个的那堆剩一个还是取完
先手必胜
③:至少有两堆大于1个:
(1)nim=0,取一次后转化为②或者③(2)
(2)nim!=0,必定可以转化为nim=0且至少有两堆大于1,也就是转化为③(1)
nim可以变为0是显然的,那么为什么剩下至少有两堆大于1呢?
举个例子:nim和二进制下 1xxxxx,那么我们知道这个最高位是其中一个大于一的堆x,现在先移除a[x],剩余n-1项 nim = nim^a[x]。
那么这个二进制数就变成了0yyyyy,当剩余还有两堆大于1的石堆时,显然成立,如果只有一堆,我们可以保证
0yyyyy中间四位存在一个1,就是剩下那堆大于2的造成的,那么移除的那一堆需要取走几个后剩下的石子数需要 xor nim
=0,那么很显然 这个被移除的堆剩下放回来的必须大于1.
分析:当初始状态为③(2),一定会在不停地取中使得自己变为②,所以③(2)状态先手必胜
当初始状态为③(1),一定会不停地取使得对方变为②,先手必败
总结:
先手必胜两种情况:
①nim=0,全是1
②nim!=0,有大于1的
代码:
#include<cstdio>
#include<cstring>
int main()
{
int n;
while (~scanf("%d",&n)){
int ans=0,x,morethan1=0;
for (int i=0;i<n;i++){
scanf("%d",&x);
ans ^= x;
if (x>1) morethan1 = 1;
}
if ((ans==0 && morethan1==0)||(ans>0 && morethan1==1)) printf("Louis\n");
else printf("Lester\n");
}
return 0;
}
博弈论暂时告一段落,学线段树去啦。