hiho一下 第四十四周 题目1 : 博弈游戏·Nim游戏

题目1 : 博弈游戏·Nim游戏

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

今天我们要认识一对新朋友,Alice与Bob。

Alice与Bob总是在进行各种各样的比试,今天他们在玩一个取石子的游戏。

在这个游戏中,Alice和Bob放置了N堆不同的石子,编号1..N,第i堆中有A[i]个石子。

每一次行动,Alice和Bob可以选择从一堆石子中取出任意数量的石子。至少取1颗,至多取出这一堆剩下的所有石子。

Alice和Bob轮流行动,取走最后一个石子的人获得胜利。

假设每一轮游戏都是Alice先行动,请你判断在给定的情况下,如果双方都足够聪明,谁会获得胜利?

输入

第1行:1个整数N。表示石子堆数。1≤N≤100

第2行:N个整数,第i个整数表示第i堆石子的个数A[i],1≤A[i]≤10000

输出

第1行:1个字符串,若Alice能够获胜输出"Alice",否则输出"Bob"

样例输入
3
3 2 1
样例输出
Bob

提示:

这一次我们讲的是一个古老而又经典的博弈问题:Nim游戏。

Nim游戏是经典的公平组合游戏(ICG),对于ICG游戏我们有如下定义:

1、两名选手;

2、两名选手轮流行动,每一次行动可以在有限合法操作集合中选择一个;

3、游戏的任何一种可能的局面(position),合法操作集合只取决于这个局面本身;局面的改变称为“移动”(move)。

4、若轮到某位选手时,该选手的合法操作集合为空,则这名选手判负。

对于第三条,我们有更进一步的定义Position,我们将Position分为两类:

P-position:在当前的局面下,先手必败。

N-position:在当前的局面下,先手必胜。

他们有如下性质:

1.合法操作集合为空的局面是P-position;

2.可以移动到P-position的局面是N-position;

3.所有移动都只能到N-position的局面是P-position。

在这个游戏中,我们已经知道A[] = {0,0,...,0}的局面是P局面,那么我们可以通过反向枚举来推导出所有的可能局面,总共的状态数量为A[1]*A[2]*...*A[N]。并且每一次的状态转移很多。

虽然耗时巨大,但确实是一个可行方法。

当然,我们这里会讲这个题目就说明肯定没那么复杂。没错,对于这个游戏有一个非常神奇的结论:

对于一个局面,当且仅当A[1] xor A[2] xor ... xor A[N] = 0时,该局面为P局面。

对于这个结论的证明如下:

1. 全0状态为P局面,即A[i]=0,则A[1] xor A[2] xor ... xor A[N] = 0。

2. 从任意一个A[1] xor A[2] xor ... xor A[N] = k != 0的状态可以移动到A[1] xor A[2] xor ... xor A[N] = 0的状态。由于xor计算的特殊性,我们知道一定有一个A[i]最高位与k最高位的1是相同的,那么必然有A[i] xor k < A[i]的,所以我们可以通过改变A[i]的值为A[i]‘,使得A[1] xor A[2] xor ... xor A[i]‘ xor
... xor A[N] = 0。

3. 对于任意一个局面,若A[1] xor A[2] xor ... xor A[N] = 0,则不存在任何一个移动可以使得新的局面A[1] xor A[2] xor ... xor A[N] != 0。由于xor计算的特殊性,我们可以知道,一定是存在偶数个1时该位置的1才会被消除。若只改变一个A[i],无论如何都会使得1的数量发生变化,从而导致A[1] xor A[2] xor ... xor A[N] != 0。

以上三条满足ICG游戏中N,P局面的转移性质,所以该结论的正确性也得到了证明。

参考代码:

#include <iostream>
using namespace std;
int main(){
    int n,x,ans;
    while (cin>>n){
        cin>>ans;
        for (int i=0;i<n-1;i++){
            cin>>x;
            ans=ans^x;
        }
        if (ans)
            cout<<"Alice"<<endl;
        else
            cout<<"Bob"<<endl;
    }
    return 0;
}
时间: 2024-12-28 16:28:03

hiho一下 第四十四周 题目1 : 博弈游戏·Nim游戏的相关文章

hiho一下 第四十周 题目1 : 三分&#183;三分求极值

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 × 提示:三分法 在之前的几周中我们了解到二分法作为分治中最常见的方法,适用于单调函数,逼近求解某点的值. 但当函数是凸形函数时,二分法就无法适用,这时就需要用到三分法. 从三分法的名字中我们可以猜到,三分法是对于需要逼近的区间做三等分: 我们发现lm这个点比rm要低,那

hiho一下 第五十四周 题目1 : 连通性&#183;三

题目1 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧. 约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径. 小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场.当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家. 一开始小

hiho一下 第四十五周 博弈游戏&#183;Nim游戏&#183;二 [ 博弈 ]

传送门 题目1 : 博弈游戏·Nim游戏·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Alice和Bob这一次准备玩一个关于硬币的游戏:N枚硬币排成一列,有的正面朝上,有的背面朝上,从左到右依次编号为1..N.现在两人轮流翻硬币,每次只能将一枚正面朝上的硬币翻过来,并且可以随自己的意愿,在一枚硬币翻转后决定要不要将该硬币左边的任意一枚硬币也翻一次(正面翻到背面或背面翻到正面).翻最后一枚正面向上的硬币的人获胜.同样的,这次游戏里面Alice仍然先手,两人均采

第四十天 一乐在其中—Android的小游戏打飞机(三)添加敌机

8月9日,晴."江城如画里,山晓望晴空.雨水夹明镜,双桥落彩虹. 人烟寒橘柚,秋色老梧桐." 上篇已经让飞机加载子弹和音效及背景音乐,本篇主要添加敌机. 本篇要用到的几个函数讲解: 1.voidsetTag (int nTag) 设置动作的标记. 2.CCRANDOM_0_1()函数生成的是 [0, 1] 之间的随机数:要生成  [0-100] 之间的数CCRANDOM_0_1 * 100:生成 [1,5]  之间的float 数,就是 CCRANDOM_0_1 * 4 + 1. 3.

hiho一下 第四十九周 题目1 : 欧拉路&#183;一【无向图 欧拉路问题】

题目1 : 欧拉路·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的角色来到了一个很大的湖边.湖上有N个小岛(编号1..N),以及连接小岛的M座木桥.每座木桥上各有一个宝箱,里面似乎装着什么道具. 湖边还有一个船夫,船夫告诉主角.他可以载着主角到任意一个岛上,并且可以从任意一个岛上再载着主角回到湖边,但是主角只有一次来回的机会.同时船夫告诉主

hihoCoder hiho一下 第四十八周 题目1 : 拓扑排序&#183;二

题意:给定一个拓扑图,其中部分结点含有1个病毒,每个结点只要收到病毒就会立即往出边所能到达的点传播,病毒数可叠加,求所有结点的病毒数总和. 思路:根据拓扑的特点,每个入度为0的点肯定不会再被传播病毒,而且会将自己的所有病毒向与其相连的结点传播.那么可以从入度味为0的点着手,逐个删除入度为0的结点,在删除的过程中,更新与其相连的结点的病毒数(即将病毒数累加到该结点),到最后所有结点都没了,各个结点所累积的病毒数的和就是答案. 1 #include<bits/stdc++.h> 2 using n

hiho一下 第四十二周

题目1 : 骨牌覆盖问题·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题? 所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢? 首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个

hiho一下 第六十四周 Right-click Context Menu

题目链接:hihocoder 第64周 题意概述: 上下文菜单是panel(面板)包括很多section(分区),一个分区里面至少包含一个菜单项.每一个菜单项都对应有一个子panel,这个panel可能为空.也可能又是一个新的包含很多分区的panel.如何安排同一个section内的菜单项顺序?如何安排同一个panel内的各个分区?才能使的展开之后最短,占的空间最少? 方法:子级菜单长度-我的菜单长度=h,对h进行排序.h大的在上面. 1 #include<iostream> 2 #inclu

hiho一下 第四十八周 拓扑排序&#183;二【拓扑排序的应用 + 静态数组 + 拓扑排序算法的时间优化】

题目1 : 拓扑排序·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当然小Hi和小Ho也参与到了其中.从大家各自了解的情况中,小Hi和小Ho整理得到了以下的信息: 校园网主干是由N个节点(编号1..N)组成,这些节点之间有一些单向的网路连接.若存在一条网路连接(u,v)链接了节点u和节点v,则节点u可以向节点v发送信息,但是节点v不能通过该链接向节点u发送信息. 在刚