nim游戏(判断必胜还是必败,必胜该怎么取)

对于n堆石子,某个人没有石子可取为输,接下来的必胜态和必败态是对于第一个人来说的.

首先是必胜态和必败态,如果不管第一个怎么取都不能胜,那么为必败态,否则为必胜态.

如果对于n堆石子数取异或值为0,则为必败态,反之为必胜态.

for (int i = 0; i < n; i ++)
{
    scanf("%lld", &a[i]);
    ans ^= a[i];
}

如果第一个人为必胜态,那么一定可以取一定的石子使第二个人取的石子为必败态.证明如下:

ans(不为0)的最高位一定为1(设为k),那么在a[n]中一定存在一个数在第k位上也为1,那么这意味着我在这一位上减少a[i]-(a[i]^ans)(a[i]一定大于a[i]^ans,即这样减一定是合理的)就能使这一位的第k位变为0,这时第i位就变成了a[i]^ans,它与其余每堆的数量异或一定为0,即为必败态.

综合代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 500010

typedef unsigned long long ULL;
ULL a[N];

int main()
{
    int n, ans = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i ++)
    {
        scanf("%lld", &a[i]);
        ans ^= a[i];
    }

    if (ans == 0)
    {
        printf("lose");
        return 0;
    }

    int k = 0, b = ans;
    while (b)//求ans的最高位,同时最好不要修改ans.
    {
        b >>= 1;
        k++;
    }
//    printf("%d %d\n", k, 10^ans);
    for (int i = 0; i < n; i ++)
    {
        if((a[i] >> k - 1) & 1)
        {
            int b = a[i] - (a[i] ^ ans);//一定要加上括号,我就没加括号wa了几次.
            printf("%d %d\n", b, i + 1);//输出修改的个数和修改的堆数.
            a[i] = a[i] ^ ans;
            break;
        }
    }
    for (int i = 0; i < n; i ++)
        printf("%d ", a[i]);//输出修改后的每堆的个数.
    return 0;
}

 这是一个最简单的nim游戏,没有太大的变化.

博主是新手,望各位大佬将问题本人的问题提出来,谢谢各位!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あなたのことが好きです319

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值