P1247 取火柴游戏 (博弈论)

本文介绍了Nim游戏的基本规则和必胜策略。当所有火柴棒的异或值不为0时,先手玩家有必胜策略。通过找到能够使异或值变为0的操作,可以确保先手玩家获胜。文章给出了AC代码示例,展示了如何找到这种操作并输出首次移动的堆号和数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:取火柴游戏 - 洛谷

题目描述

输入 k及 k个整数 n1​,n2​,…,nk​,表示有 k 堆火柴棒,第 ii堆火柴棒的根数为ni​;接着便是你和计算机取火柴棒的对弈游戏。取的规则如下:每次可以从一堆中取走若干根火柴,也可以一堆全部取走,但不允许跨堆取,也不允许不取。

谁取走最后一根火柴为胜利者。

输入格式

第一行,一个正整数 k。

第二行,k个整数 n1​,n2​,…,nk​。

输出格式

如果是先取必胜,请在第一行输出两个整数 a,b,表示第一次从第 b 堆取出 a个。第二行为第一次取火柴后的状态。如果有多种答案,则输出 <b,a>字典序最小的答案 ( 即 b 最小的前提下 a最小 )。

如果是先取必败,则输出“lose”。

Nim游戏

(转载)Nim游戏博弈(收集完全版) - exponent - 博客园

博弈论 套路开始的地方(NIM游戏和Sprague-Grundy函数)_隐形的稻草人哦的博客-优快云博客

在普通Nim游戏中,a1^a2^a3^……^an=0是必败态

如果一开始 a1^a2^a3^……^an=0,那么先手必败;如果一开始不为0,那么一定可以让一堆石子中的数减小使得下一轮a1^a2^a3^……^an=0

而只要从前往后找到(x ^ a[i]) < a[i]),那么新的a[i]值就是x ^ a[i],可以让异或结果变为0

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n)

const int N = 5e5 + 10;
int a[N];

int main()
{
    int n;
    cin >> n;
    int x = 0;
    rep(i, n) cin >> a[i], x ^= a[i];
    if(x == 0)
    {
        cout << "lose";
    }
    else
    {
        rep(i, n)
        {
            if((x ^ a[i]) < a[i])
            {
                cout << a[i] - (x ^ a[i]) << " " << i << endl;
                a[i] = a[i] ^ x;
                break;
            }
        }
        rep(i, n) cout << a[i] << " ";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值