3032题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3032
5795题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795
3032题意:Nim博弈,不过取的时候可以将一堆分成任意两堆。
5795题意:可将一堆分成三堆。
SG函数打表找规律。
3032打表程序:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
int i, j;
int sg[1010], mex[1010];
sg[0] = 0, sg[1] = 1;
for(i = 2; i <= 1000; i++) {
memset(mex, 0, sizeof mex);
for(j = 1; j <= i/2; j++) {
mex[sg[j]^sg[i - j]] = 1;
}
for(j = 1; j <= i; j++) {
mex[sg[i - j]] = 1;
}
for(j = 0; ; j++) {
if(mex[j] == 0) {
sg[i] = j;
break;
}
}
}
for(i = 0; i <= 100; i++) {
printf("sg[%d] : %d\n", i, sg[i]);
}
return 0;
}
sg(0) = 0,sg(1) = 1。
状态2的后继有:0,1和(1,1),他们的SG值分别为0,1,0,所以sg(2) =2。 (sg[(1,1] = sg[1] ^ sg[1])
状态3的后继有:0、1、2、(1,2),他们的SG值分别为0、1、2、3,所以sg(3) = 4。 (sg[(1,2] = sg[1] ^ sg[2])
状态4的后继有:0、1、2、3、(1,3)和(2,2),他们的SG值分别为0,1,2,4,5,0,所以sg(4) = 3.
可以发现规律为:
n能整除4时,sg[n] = n - 1
n%4 == 3时,sg[n] = n + 1
否则sg[n] = n
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[1000100];
int main() {
int t;
scanf("%d", &t);
while(t--) {
int n;
scanf("%d", &n);
int i;
for(i = 0; i < n; i++) {
scanf("%d", a + i);
}
int ans = 0;
for(i = 0; i < n; i++) {
if(a[i] % 4 == 0) {
ans ^= (a[i] - 1);
}
else if(a[i] % 4 == 3) {
ans ^= (a[i] + 1);
}
else ans ^= a[i];
}
if(ans) puts("Alice");
else puts("Bob");
}
return 0;
}
5795打表程序:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
int i, j, k;
int sg[1010], mex[1010];
sg[0] = 0, sg[1] = 1;
for(i = 2; i <= 1000; i++) {
memset(mex, 0, sizeof mex);
for(j = 1; j <= i; j++) {
for(k = 1; k <= i; k++) {
if(j + k < i) {
mex[sg[j]^sg[k]^sg[i - j - k]] = 1;
}
}
}
for(j = 1; j <= i; j++) {
mex[sg[i - j]] = 1;
}
for(j = 0; ; j++) {
if(mex[j] == 0) {
sg[i] = j;
break;
}
}
}
for(i = 0; i <= 100; i++) {
printf("sg[%d] : %d\n", i, sg[i]);
}
return 0;
}
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[1000010];
int main() {
int t;
scanf("%d", &t);
while(t--) {
int n;
scanf("%d", &n);
int i;
for(i = 0; i < n; i++) {
scanf("%d", a + i);
}
int ans = 0;
for(i = 0; i < n; i++) {
if(a[i] % 8 == 0) {
ans ^= (a[i] - 1);
}
else if(a[i] % 8 == 7) {
ans ^= (a[i] + 1);
}
else ans ^= a[i];
}
if(ans) puts("First player wins.");
else puts("Second player wins.");
}
return 0;
}