链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795
题意:n堆石子,每次可以选择取走一堆中的若干个或者把一堆分成三个非空堆,取到最后一个石子获胜。问先手必胜还是后手必胜。
思路:打表找出sg函数的规律。发现sg[8k+7]=8k+8,sg[8k+8]=8k+7。其余情况下sg[x]=x。打表思路:x大于等于3时,对把x分成三个数的每种情况的sg值取亦或(亦或运算的结合性)。
附打表代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
//int sg[105];
//void init(){
// for (int i = 1; i <= 100; i++){
// set<int>s;
// for (int j = 1; j <= i; j++){
// s.insert(sg[i - j]);
// }
// if (i >= 3){
// for (int j = 1; j < i - 2;j++)
// for (int k = 1; k < i - 2;k++)
// if (j + k < i)
// s.insert(sg[j] ^ sg[k] ^ sg[i - j - k]);
// }
// int g = 0;
// while (s.count(g))g++;
// sg[i] = g;
// printf("i:%d sg[i]:%d\n", i, sg[i]);
// }
//}
int main(){
int t, n, c, x;
//init();
cin >> t;
while (t--){
scanf("%d", &n);
c = 0;
for (int i = 0; i < n; i++){
scanf("%d", &x);
if ((x - 7) % 8 == 0)c ^= (x + 1);
else if ((x - 8) % 8 == 0)c ^= (x - 1);
else c ^= x;
}
if (c == 0)
printf("Second player wins.\n");
else
printf("First player wins.\n");
}
return 0;
}
博主菜鸡,有问题欢迎指正!