[BZOJ 1874] [BeiJing2009 WinterCamp] 取石子游戏

Description

每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏。请你求出是否有先手必胜策略,如果有,第一步如何取石子。

Solution

当各堆的 \(SG\) 函数的异或和不为 \(0\) 时为必胜态,证明如下

Code

#include <cstdio>

int n, m, ans, a[15], b[15], sg[1005], f[15];

void getsg() {
    for (int i = 1; i <= 1000; ++i) {
        for (int j = 1; j <= m; ++j)
            if (i - b[j] >= 0) f[sg[i-b[j]]] = i;
        for (int j = 0; j <= 10; ++j)
            if (f[j] != i) { sg[i] = j; break; }
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i) scanf("%d", &b[i]);
    getsg();
    for (int i = 1; i <= n; ++i) ans ^= sg[a[i]];
    if (!ans) puts("NO");
    else {
        puts("YES");
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
                if ((ans ^ sg[a[i]] ^ sg[a[i]-b[j]]) == 0) {
                    printf("%d %d\n", i, b[j]); return 0;
                }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fly-in-milkyway/p/10009693.html
今日推荐