简单SG函数及应用
// 简单SG函数模板
int sg[maxn];
bool vis[maxn];
int SG(int n) {
memset(sg, 0, sizeof sg);
sg[0] = 0;// 初始状态
for (int i = 1; i <= n; ++i) {// 递推
memset(vis, 0, sizeof vis);
for (int j = 0; j < i; ++i) {// 相关状态
int tmp = sg[j] ^ sg[i - j];// 如果可以分成多个子游戏, 值就是他们的sg异或
vis[tmp] = 1;
}
for (int j = 0; ; ++j) if (!vis[j]) {
sg[i] = j; break;
}
}
return sg[n];
}
例题:HDU - 3980
const int maxn = 2e2 + 10;
int sg[1010];
bool vis[1010];
int SG(int n, int m) {
memset(sg, 0, sizeof sg);
for (int i = m; i <= n; ++i) {
memset(vis, 0, sizeof vis);
for (int j = m; j <= i; ++j) {
int tmp = sg[j - m] ^ sg[i - j];// 两个sg游戏相异或
vis[tmp] = 1;
}
for (int j = 0; ; ++j)
if (!vis[j]) {
sg[i] = j;
break;
}
}
return sg[n];
}
int cas = 1;
signed main() {
int t; scanf("%d", &t);
while (t--) {
int n, m;
scanf("%d %d", &n, &m);
printf("Case #%d: ", cas++);
if (m > n) puts("abcdxyzk");
else {
n -= m;// 一开始是环,怎么拿连续m个都是等价的
// 所以直接拿掉m个后环变成直线,然后以后手为先手
if(m > n) puts("aekdycoin");
else {
SG(n, m);
if (sg[n]) puts("abcdxyzk");
else puts("aekdycoin");
//printf("%d\n", sg[n]);
}
}
}
return 0;
}
const int maxn = 2e3 + 10;
short sg[maxn][maxn];
bool vis[maxn];
int SG(int n, int m) {
sg[1][1] = 0; sg[2][1] = sg[2][2] = 1;
for (int i = 3; i <= n; ++i) {
sg[i][1] = !sg[i - 1][1];
for (int j = 2; j <= i; ++j) {// 很明显的只有最多四种状态
vis[0] = 0; vis[1] = 0; vis[2] = 0; vis[3] = 0;
vis[sg[i][j - 1]] = vis[sg[i - 1][j - 1]] = 1;
if (i != j) vis[sg[i - 1][j]] = 1;
for (int k = 0; ; ++k) if (!vis[k]) {
sg[i][j] = k; break;
}
}
}
return sg[n][m];
}
signed main() {
int n, m;
//SG(2000, 2000);
//for (int i = 1; i <= 10; ++i) {
// for (int j = 1; j <= i; ++j) {
// printf("%d%c", sg[i][j], j == i ? '\n' : ' ');
// }
//}
while (~scanf("%d %d", &n, &m), n + m) {
n %= 2; m %= 2;
if(!(n && m)) puts("Wonderful!");
else puts("What a pity!");
//if (n < m) swap(n, m);
//if (sg[n][m]) puts("Wonderful!");
//else puts("What a pity!");
}
return 0;
}
const int maxn = 1e2 + 10;
int heap[maxn][maxn];
int sg[maxn * maxn];
bool vis[maxn];
int s[maxn];
int k;
int SG(int n) {
memset(sg, 0, sizeof sg);
for (int i = 1; i <= n; ++i) {
memset(vis, 0, sizeof vis);
for (int j = 0; j < k && s[j] <= i; ++j)
vis[sg[i - s[j]]] = 1;
for (int j = 0; ; ++j) if (!vis[j]) {
sg[i] = j; break;
}
}
return sg[n];
}
signed main() {
while (~scanf("%d", &k), k) {
for (int i = 0; i < k; ++i) scanf("%d", &s[i]);
sort(s, s + k);
int m; scanf("%d", &m);
int maxx = -1;
for (int i = 0; i < m; ++i) {
scanf("%d", &heap[i][0]);
for (int j = 1; j <= heap[i][0]; ++j) {
scanf("%d", &heap[i][j]); maxx = max(maxx, heap[i][j]);
}
}
SG(maxx);
for (int i = 0; i < m; ++i) {
int tmp = 0;
for (int j = 1; j <= heap[i][0]; ++j) tmp ^= sg[heap[i][j]];// 多堆异或和
if (tmp) printf("W");
else printf("L");
}
puts("");
}
return 0;
}

浙公网安备 33010602011771号