51nod 1069 Nim游戏

来源:互联网 发布:php strcmp函数 编辑:程序博客网 时间:2024/06/11 00:17
有N堆石子。A B两个人轮流拿,A先拿。每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出N及每堆石子的数量,问最后谁能赢得比赛。

例如:3堆石子,每堆1颗。A拿1颗,B拿1颗,此时还剩1堆,所以A可以拿到最后1颗石子。


Nim游戏。

(Bouton's Theorem):对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算。

怎么样,是不是很神奇?我看到它的时候也觉得很神奇,完全没有道理的和异或运算扯上了关系。但这个定理的证明却也不复杂,基本上就是按照两种position的证明来的。

根据定义,证明一种判断position的性质的方法的正确性,只需证明三个命题: 1、这个判断将所有terminal position判为P-position;2、根据这个判断被判为N-position的局面一定可以移动到某个P-position;3、根据这个判断被判为P-position的局面无法移动到某个P-position。

第一个命题显然,terminal position只有一个,就是全0,异或仍然是0。

第二个命题,对于某个局面(a1,a2,...,an),若a1^a2^...^an!=0,一定存在某个合法的移动,将ai改变成ai'后满足a1^a2^...^ai'^...^an=0。不妨设a1^a2^...^an=k,则一定存在某个ai,它的二进制表示在k的最高位上是1(否则k的最高位那个1是怎么得到的)。这时ai^k<ai一定成立。则我们可以将ai改变成ai'=ai^k,此时a1^a2^...^ai'^...^an=a1^a2^...^an^k=0。

第三个命题,对于某个局面(a1,a2,...,an),若a1^a2^...^an=0,一定不存在某个合法的移动,将ai改变成ai'后满足a1^a2^...^ai'^...^an=0。因为异或运算满足消去率,由a1^a2^...^an=a1^a2^...^ai'^...^an可以得到ai=ai'。所以将ai改变成ai'不是一个合法的移动。证毕。

根据这个定理,我们可以在O(n)的时间内判断一个Nim的局面的性质,且如果它是N-position,也可以在O(n)的时间内找到所有的必胜策略。Nim问题就这样基本上完美的解决了。

(以上来自百度百科)


如果Nim游戏中的规则稍微变动一下,每次最多只能取K个,怎么处理?

方法是将每堆石子数mod (k+1).


#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <queue>using namespace std ; int const maxn = 1005 ;int a[maxn];int main(){int n;//scanf("%d",&t);while(cin>>n){//scanf("%d",&n);int ans = 0; for(int i = 0 ; i < n ;i++){cin>>a[i];//scanf("%d",&a[i]);ans^=a[i];}if(ans==0)puts("B");else puts("A");}return 0;}



0 0
原创粉丝点击