博弈论(简单题目)

题目:(最简单的博弈论)

给定 n堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。

问如果两人都采用最优策略,先手是否必胜。

输入格式

第一行包含整数 n。

第二行包含 n个数字,其中第 i个数字表示第 i 堆石子的数量。

输出格式

如果先手方必胜,则输出 Yes

否则,输出 No

数据范围

1≤n≤10^5,
1≤每堆石子数≤10^9

输入样例:

2
2 3

输出样例:

Yes

(题目摘自www.acwing.com) 

题解思路:

当先手面临,所有石子堆全部变为0的状态时,此时先手必败,所以定义如果先手能够走到一个必败的状态时,称其为先手必败状态,反之为先手必胜状态。

本题利用一个既定的结论,在这里不做证明(利用异或进行求解,很难想到),一共有n堆石子,从a1,a2,a3……an.一共存在两种情况:

a1^a2^a3……^an=0(先手必败)

a1^a2^a3……^an≠0(先手必胜)

异或:两个二进制数,相同位相同为0,不同为1。

证明:

①:0^0^0^……0=0,第一种情况很明显可以看出为0。

②:a1^a2^a3……^an=x≠0,这种情况,x的二进制表示中最高一位的1在第k位,则a1到an中必定存在一个ai,ai的第k位为1,则ai^k<ai。

在这里举一个例子,ai:11001001101,x为00001010010,则ai^x必定小于ai。

则从第ai堆石子中取走ai-(ai^x)个,ai堆石子剩余ai^k个石子,则取完以后:

a1^a2^……ai^k^ai+1……^an=x^x=0,所以说明当a1^a2^a3……^an=x≠0时,先手总可以取走若干个石子,使得后手处于a1^a2^a3……^an=0的状态,直到游戏即将结束时,先手取走若干的石子,此时后手必定面临0^0^0^……0=0的状态,则先手必胜。

③:a1^a2^a3……^an=0,这种情况下,先手遇到的为0,抛给后手的一定不为0,所以最终

0^0^0^……0=0的状态一定会被先手遇到,所以先手必败,所以可以有以上的结论。

所以可以有以下代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;scanf("%d",&n);
    int res=0;
    while(n--)
    {
        int x;scanf("%d",&x);
        res^=x;
    }
    if(res)puts("Yes");
    else puts("No");
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不要学编程。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值