Sicily 1922. Winning Ways

尼姆博奕(Nimm Game)

两个人从N堆石子中的任意一堆任取1个或多个,取到没得取得人为负者。

奇异局势

如果面对一种局势的人是必败的,那么这种局势叫做奇异局势。比如如果N堆石子都是0个,那么先取者面对的(0,0,0,…,0)就是一种奇异局势。

如果我想让我的对手输,我会想尽办法让他面对奇异局势。

奇异局势有这样一种性质,比如现在的N堆石子的数目为a1,a2,a3,…,aN,那么:

a1⊕a2⊕a3⊕…⊕aN=0。

a1⊕a2⊕a3⊕…⊕aN一般称为Nim-sum

为什么Nim-sum=0的局势是奇异局势?

也就是说,为什么当玩家面对Nim-sum=0的时候,他是必输的?

这篇论文有比较好的解释:

http://web.mit.edu/sp.268/www/nim.pdf

下面试着翻译为中文:

证明:如果一个玩家想在尼姆博奕的游戏中胜出,他应该让Nim-sum值为0。

引理1 如果在某一轮中Nim-sum=0,那么下一次的操作必然会改变Nim-sum。

证:

令x1,x2,…,xn表示操作前N堆石子的个数,s表示操作前N堆石子的Nim-sum,那么:

s=x1⊕x2⊕x3⊕…⊕xn;

令y1,y2,…,yn表示操作后N堆石子的个数,t表示操作后N堆石子的Nim-sum,那么:

t=y1⊕y2⊕y3⊕…⊕yn;

令操作中改变的石子堆标号为k,那么在操作后必然有xk!=yk,且对于i!=k来说必然有xi=yi,说白了就是改变一个且只有一个石子堆。

那么:

t = 0 ⊕ t

= s ⊕ s ⊕ t

= s ⊕ (x1 ⊕ x2 ⊕ … ⊕ xn) ⊕ (y1 ⊕ y2 ⊕ … ⊕ yn)

= s ⊕ (x1 ⊕ y1) ⊕ (x2 ⊕ y2) ⊕ … ⊕ (xk ⊕ yk)

= s ⊕ xk ⊕ yk

由于xk!=yk,所以xk ⊕ yk != 0,而我们知道在操作前的Nim-sum=0,也就是s为0,所以t != 0,证毕。

引理二如果在某一轮中Nim-sum != 0,那么下一次的操作可以改变Nim-sum使其为0。

证:

以下字母除了说明都与引理一定义相同。

令d是s的最高有效位,我们选取一个石子堆xk,xk的最高有效位也是d(这是一定可以找得到的,因为s=x1⊕x2⊕x3⊕…⊕xn)。

那么令yk = s ⊕ xk,由于最高有效位相同,s ⊕ xk的值必然小于等于xk,比如 s = 100010,

xk= 101010,

此时yk= 001000≤xk。

所以我们总能够从xk中拿走xk ? yk个石子使得yk = s ⊕ xk。

那么t = s ⊕ xk ⊕ yk(由引理一)

= s ⊕ xk ⊕ xk ⊕ s

= s ⊕ s ⊕ xk ⊕ xk

= 0

证毕。

现在我们来回答开头的问题:为什么当玩家面对Nim-sum=0的时候,他是必输的?

当玩家A面对Nim-sum=0的时候,由引理一,他必然会使得Nim-sum!=0;由引理二,下一轮玩家B面对Nim-sum!=0时,他完全可以使Nim-sum=0。

如此循环往复,最后石子堆的情况将会是Nim-sum=0的极限情况,也就是a1=0,a2=0,…,an=0。

那么玩家A输定了。

思路

所以,这题中的问题是先手玩家有几种方法可以在第一轮操作后的石子堆为Nim-sum=0的状态,其实也就是引理二中的内容了。

先将游戏刚开始的Nim-sum算出来;

如果Nim-sum=0,那么先手玩家面对的就是奇异局势,他根本没有办法赢,方法数为0;

否则,由引理二,统计(Nim-sum ^ xi) <= xi的个数就是赢的方法数。

代码

#include <stdio.h>

int main() {

    int CaseNum;
    scanf("%d\n", &CaseNum);

    while (CaseNum--) {

        int N, Sum = 0, Stones[50005], k = 0, XorSum = 0;
        scanf("%d\n", &N);
        char C[600000];
        gets(C);

        // Use the gets() function to read a line with lots of datas is fast than scanf()
        for (int i = 0; C[i] != ‘\0‘; i++) {
            if (C[i] == ‘ ‘) {
                Stones[k++] = Sum;
                Sum = 0;
            } else {
                Sum = Sum * 10 + C[i] - ‘0‘;
            }
        }
        Stones[k] = Sum;

        for (int i = 0; i < N; i++) XorSum ^= Stones[i];
        if (XorSum == 0) printf("0\n");
        else {
            int Ways = 0;
            for (int i = 0; i < N; i++) if ((XorSum ^ Stones[i]) <= Stones[i]) Ways++;
            printf("%d\n", Ways);
        }

    }

    return 0;
}
时间: 2024-11-03 05:41:47

Sicily 1922. Winning Ways的相关文章

HDU 3544 (不平等博弈) Alice&#39;s Game

切巧克力的游戏,想得还是不是太明白. 后者会尽量选前着切后其中小的一块来切,那么先手须尽量取中间来切. So?题解都是这么一句话,不知道是真懂了还是从别人那抄过来的. 后来找到一个官方题解,分析得比较认真,但我这智商还是没懂太多,QAQ 本题我抄袭自<Winning Ways for your Mathematical Plays> ,一本关于游戏论的科普类图书.这题是一个组合游戏,但是并不是一个对等的组合游戏,所以试图使用 SG 函数相关知识解答是会面临巨大的挑战的. 书中本题的做法描述得十

CYPHER 语句(Neo4j)

创建电影关系图 查找 新增 修改 删除 导入 创建电影关系图 CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'}) CREATE (Keanu:Person {name:'Keanu Reeves', born:1964}) CREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967}) CREATE

Neo4j 文档

Graph Fundamentals 基础 Basic concepts to get you going. A graph database can store any kind of data using a few simple concepts: Nodes - graph data records 节点 Relationships - connect nodes 关系 Properties - named data values 属性 A Graph Database Neo4j st

Facebook Hacker Cup 2015 Round 1 Winning at Sports (附带测试数据)

题目描述: Winning at Sports25 points In the game of Sports, the object is have more points than the other team after a certain amount of time has elapsed. Scores are denoted by two hyphen-separated integers. For example, scores may include 3-2, 4-1, or 1

91. Decode Ways

原题目: A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example,Given enc

HDU 1978 How many ways(记忆化)

Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 1.机器人一开始在棋盘的起始点并有起始点所标有的能量. 2.机器人只能向右或者向下走,并且每走一步消耗一单位能量. 3.机器人不能在原地停留. 4.当机器人选择了一条可行路径后,当他走到这条路径的终点时,他将只有终点所标记的能量. 如上图,机器人一开始在(1,1)点,并拥有4单位能量,蓝色方块表示他所能到达的点,如果他在这次路径选择中选择的终点是(2,4)

[LeetCode] decode ways 解码方式

A message containing letters fromA-Zis being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example,Given encoded me

LeetCode 241. Different Ways to Add Parentheses

241. Different Ways to Add Parentheses Add to List Description Submission Solutions Total Accepted: 38849 Total Submissions: 92740 Difficulty: Medium Contributors: Admin Given a string of numbers and operators, return all possible results from comput

091. Decode Ways

1 class Solution { 2 public: 3 int numDecodings(string s) { 4 if (s.size() == 0) return 0; 5 else { 6 vector<int> ways(s.size(), 0); 7 if (s[0] >= '1' && s[0] <= '9') ways[0] = 1; 8 else ways[0] = 0; 9 if (s[1] >= '1' && s[1