原文链接: HDU 1944 && 1536 SG NIM 博弈
上一篇: HDU 5795 NIM SG计算
下一篇: POJ 3070 简单快速幂
题意:首先输入K 表示一个集合的大小
之后输入集合 表示对于这对石子只能去这个集合中的元素的个数
之后输入一个m 表示接下来对于这个集合要进行m次询问
之后m行 每行输入一个n 表示有n个堆 每堆有n1个石子 问这一行所表示的状态是赢还是输 如果赢输入W否则L
234ms
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 10001
int f[N], sg[N];
bool mex[N];
void get_sg(int t, int n){
int i, j;
memset(sg, 0, sizeof(sg));
for (i = 1; i <= n; i++){
memset(mex, 0, sizeof(mex));
// 对于属于g(x)后继的数置1
for (j = 0; j < t && f[j] <= i; j++)
mex[sg[i - f[j]]] = 1;
// 找到最小不属于该集合的数
for (j = 0; j <= n; j++)
if (!mex[j])
break;
sg[i] = j;
}
}
int main(){
int k, m, n, i, t, temp;
while (scanf("%d", &k) && k){
for (i = 0; i < k; ++i)
scanf("%d", &f[i]);
sort(f, f + k);
get_sg(k, N);
scanf("%d", &m);
while (m--){
temp = 0;
scanf("%d", &n);
for (i = 0; i < n; ++i){
scanf("%d", &t);
temp ^= sg[t];
}
if (!temp) printf("L");
else printf("W");
}
printf("\n");
}
return 0;
}
187ms
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
int const MAX = 10001;
int const INF = 1 << 30;
double const EPS = 0.00000001;
using namespace std;
int k, m, t, ans, n;
int a[101], sg[MAX];
bool vis[MAX];
void getSg(){
memset(sg, 0, sizeof(sg));
for (int i = 1; i < MAX; i++){
memset(vis, 0, sizeof(vis));
for (int j = 0; j < k && a[j] <= i; j++)
vis[sg[i - a[j]]] = 1;
int j = 0;
while (vis[j]) j++;
sg[i] = j;
}
}
int main(){
while (scanf("%d", &k) == 1 && k){
for (int i = 0; i < k; i++)
scanf("%d", a + i);
sort(a, a + k);
getSg();
scanf("%d", &m);
while (m--){
scanf("%d", &n);
ans = 0;
while (n--){
scanf("%d", &t);
ans ^= sg[t];
}
printf("%s", ans ? "W" : "L");
}
printf("\n");
}
return 0;
}