有一堆棋子在棋盘上, A和B轮流走, 每次可以取一个棋子向上或向左走任意步, 或者向上以及向右走x步, 最先把一个棋子移动到0 0的人赢, 问A能不能赢.
SG
保证当前状态的子状态的sg都已经求出. 把子状态的sg放入集合, 第一个不在集合中的数就是当前状态的sg.
这个题中, 第0行和第0列以及对角线上都是不可达的状态, 没有人会主动把棋子移动到这些位置. 所以说没有人的子状态会是这些点, 这一点要特别注意.
int sg[105][105];
int mex[10005];
void SG() {
for (int i = 0; i <= 100; i++) {
for (int j = 0; j <= 100; j++) {
if (i == 0 || j == 0 || i == j)continue;
memset(mex, 0, sizeof(mex));
int mx = big(i, j);
for (int k = 1; k <= mx; ++k) {
if (i > k && i - k != j)mex[sg[i - k][j]] = 1;
if (j > k && j - k != i)mex[sg[i][j - k]] = 1;
if (i > k && j > k)mex[sg[i - k][j - k]] = 1;
}
int tmp = 0;
for (int t = 0; t < 10005; t++) {
if (mex[t] == 0) {
tmp = t;
break;
}
}
sg[i][j] = tmp;
}
}
}
int main() {
SG()
int n;
scanf("%d", &n);
int onDiagonal = 0;
int ans = 0;
for (int i = 0; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
if (x == y) {
onDiagonal = 1;
break;
}
ans ^= sg[x][y];
}
if (onDiagonal)puts("Y");
else if (ans == 0)puts("N");
else puts("Y");
return 0;
}