Loading

HDU-3032 Nim or not Nim?

Nim or not Nim?

两个人进行博弈轮流操作,有 \(n\) 堆石子,每堆石子有 \(a_i\) 个石子,每次操作可以取一堆里的若干个石子,但至少一个,或将一堆石子分成两堆

尼姆博弈变种 打表

可以通过sg函数先打表分析每一种情况,再得出结论

\(sg[i] = mex(sg[0], sg[1],...,sg[i-1], sg[1] \bigoplus sg[i-1], sg[2] \bigoplus sg[i-2]....)\)

通过打表分析,除了被4整除的和除4余3的数字sg函数变化了以外,其余的 \(sg[i] = i\),而且变化的规律也很好找,打一打表就知道了

AC代码

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e6 + 10;
int num[maxn];

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        for(int i=0; i<n; i++) scanf("%d", &num[i]);
        for(int i=0; i<n; i++)
        {
            if(num[i] % 4 == 3) num[i]++;
            else if(num[i] % 4 == 0 && num[i]) num[i]--;
        }
        int ans = 0;
        for(int i=0; i<n; i++)
            ans ^= num[i];
        printf("%s\n", ans ? "Alice" : "Bob");
    }
    return 0;
}

暴力打表

#include <iostream>
using namespace std;
const int maxn = 1010;
int sg[maxn], vis[maxn], f[maxn];

void get_sg(int n)
{
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<=maxn; j++) vis[j] = 0;
        for(int j=0; j<i; j++) vis[sg[j]] = 1;
        for(int j=1; j<i; j++)
            vis[sg[j] ^ sg[i-j]] = 1;
        for(int j=0; j<maxn; j++)
        {
            if(vis[j] == 0)
            {
                sg[i] = j;
                break;
            }
        }
    }
}

int main()
{
    int n;
    cin >> n;
    get_sg(n);
    for(int i=0; i<=n; i++)
    {
        cout << i << " : " << sg[i] << endl;
    }
    return 0;
}
posted @ 2022-04-27 16:28  dgsvygd  阅读(16)  评论(0编辑  收藏  举报