这道题跟刘汝佳书上的例题一模一样
先给出题目的意思:有n堆石子,分别有a1,a2,......an个,两个游戏者轮流操作,每次可以选一堆,拿走至少一个石子,但不能超过一半的石子。谁不能取,就算输
给出数据范围(T<=100)。每组数据的第一行为整数n(1<=n<=100),第二行包括a1,a2,......,an(1<=ai<=2*1e18)
首先一个不用想都知道的东西,大家先求出单个游戏的值,然后在异或起来,这样便可以求值
但是这个跟nim博弈不同点就在于这个东西的取法是不能超过一半的石子,这就有点蛋疼了,但是数据范围又有点大,有不好找到明显的一方能明明白白安排对方的结论,这时便考虑打表找规律,事实上刘汝佳的书也是找的规律
(这个规律也同时教了我一点,有时候规律也可以分成奇偶分,但是要在题目上面合理假设)
下面是代码:
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<iostream> 5 using namespace std; 6 int t,n,a; 7 8 int sg(int b){ 9 if(b%2==0) return b/2; 10 else return sg(b/2); 11 } 12 13 int main(){ 14 scanf("%d",&t); 15 for(int kase=1;kase<=t;kase++){ 16 scanf("%d",&n); 17 int ans=0; 18 while(n--){ 19 scanf("%d",&a); 20 ans^=sg(a); 21 } 22 printf("Case %d: ",kase); 23 if(ans==0) printf("Bob\n"); 24 else printf("Alice\n"); 25 } 26 return 0; 27 }