【博弈论】尼姆博弈

介绍:
有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

正解

每堆物品的数量进行异或运算 结果等于0 就是奇异局势 就是必败态

原理

我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。

这些局势都满足 a^ b ^c=0

而异或运算法则是 相同为0 不同为1 根据运算法则 面对奇异局你不论怎么拿 都不会还=0(满足性质2)

而不满足的a^ b ^c=0的局势 我们都可以使其变成a^ b^c=0

因为 局面(a,b,c) 我们只要令最大的数 比如是a 令a=b+c 就变成了 (b+c)^ b^ c=(b^ b)+(c^c)=0(满足性质1)

所以 a^b ^c=0就是i我们要找的奇异局势 必败状态
————————————————————————————————————
类型一:先手的人想赢,第一步有多少种选择呢?

#include<stdio.h>
#include<math.h>
 
int a[105];
int main()
{
    int i,j,k;
    int n;
    while(~scanf("%d",&n))
    {
        if(n == 0)
            break;
        int ans = 0;
        int count = 0;
        for(i = 0;i < n;i++)
        {
            scanf("%d",&a[i]);
            ans = ans ^ a[i];
        }
        int s;
        for(i = 0;i < n;i++)
        {
            s = ans ^ a[i];
            if(s < a[i])
                count++;
        }
        printf("%d\n",count);
    }
    return 0;
}

这里我想说的是:我们可以先跳过某个数a[i],先对除其之外的所有数求XOR和,如果这个 XOR和<a[i] 那么说明有戏啦!我只需要抽走a[i]-XOR个数字,那么对方面临的就是奇异局势必败态了。

类型二:先取完的人是winner(先取完者判)。
这个时候直接求Nim和,若Nim和是0,那么先手面临奇异局势,则winner是后手;反之是先手

类型三:反尼姆博弈(先取完者判)
反尼姆博弈结论:n堆物品,全部异或结果为ans,统计富裕堆的个数为c;

先手胜有两种情况:

1:各堆石子数目异或结果不等于0,且存在有石子数目大于1的石子堆。
2:各堆石子数目异或结果等于0,且所有石子堆数目全部为1。(即所有堆都为1,且堆的数量为偶数)
在这里插入图片描述
借用国家集训队贾志豪的论文才看懂(太菜了…)hiahiahia

#include<cstdio>
int main()
{
    int t,m,n;
    scanf("%d",&t);
    while(t--)
    {
        int ans=0,c=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&m);
            if(m>1) c++;//统计富裕堆个数
            ans^=m;
        }
        if((!ans && c<2) || (ans && c)) printf("先手胜\n");
        else printf("后手胜\n");
    }
    return 0;
}
发布了71 篇原创文章 · 获赞 5 · 访问量 3401

猜你喜欢

转载自blog.csdn.net/Rainfoo/article/details/103130283