zoukankan      html  css  js  c++  java
  • 喵哈哈村的魔法考试 Round #6 (Div.3) E

    喵哈哈村的代码传说 第五章 找规律

    发布时间: 2017年3月11日 16:04   最后更新: 2017年3月11日 16:04   时间限制: 1000ms   内存限制: 128M

    桌面上有n组牌,每组牌有a[i]个扑克,两个玩家轮流拿扑克,谁拿到最后一张扑克,谁就胜利了。

    但是这个规矩有点奇怪:他们可以选择一堆拿任意多的扑克牌,或者选择使得某一堆扑克牌变成三堆任意大小的扑克牌。

    请问如果两个人都非常机智的话,谁能获胜呢?

    第一行包括数据组数T,表示测试数据组数。
    接下来T组测试数据:
    第一行一个n,表示有n组牌。
    第二行n个数字a[i],表示每组牌的数量。

    保证n<=1000000,a[i]<=1e9

    第一个人胜利输出First player wins.
    第二个人胜利输出Second player wins.

    复制
    2
    2
    4 4
    3
    1 2 4
    Second player wins.
    First player wins.
    
    一看到题目,找规律?
    这不简单? 然后就开始找规律...2的倍数 3的倍数 各种模?

    博弈论--sg函数
    sg函数定义:sg(x)=mex{y|sg(y)} y为x可以到达的子状态,mex为集合中未出现的最小整数
    还有一个结论
    直接说结论好了。(Bouton's Theorem)对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算。
    怎么样,是不是很神奇?我看到它的时候也觉得很神奇,完全没有道理的和异或运算扯上了关系。但这个定理的证明却也不复杂,基本上就是按照两种position的证明来的。
    所以对于一个由多个子游戏组成的游戏,直接 sg(i1)^sg(i2)^sg(i3)...
    枚举一下发现 当sg=k*8+7 时,sg有子状态k*8+7 举个栗子...sg=7 它可以分成小游戏 1 2 4三堆牌, 从这三堆牌里面拿 sg异或和为7,所以此时sg应该为8...
    找到这个规律之后...就是简单的取石子游戏了(Nim)
     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 typedef long long ll;
     5 ll n, m;
     6 int main(){
     7     cin>>n;
     8     while(n--){
     9         cin>>m; 
    10         ll a, sg=0;
    11         for(int i=0; i<m; i++){
    12             cin>>a;
    13             if(a%8==7)    a=a+1;
    14             else if(a%8==0) a=a-1;
    15             sg=sg^a;
    16         }
    17         if(sg!=0) printf("First player wins.
    ");
    18         else printf("Second player wins.
    ");
    19     }
    20     return 0;
    21 }
  • 相关阅读:
    小猫爬山
    方格取数
    Bash 脚本编程
    树链剖分学习笔记
    输入输出优化
    没有上司的舞会
    线性dp 之 麻烦的聚餐
    飞翔
    挖地雷
    The Prices
  • 原文地址:https://www.cnblogs.com/ledoc/p/6558910.html
Copyright © 2011-2022 走看看