zoukankan      html  css  js  c++  java
  • 洛谷 P4301 [CQOI2013]新Nim游戏 解题报告

    P4301 [CQOI2013]新Nim游戏

    题目描述

    传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同)。两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴。可以只拿一根,也可以拿走整堆火柴,但不能同时从超过一堆火柴中拿。拿走最后一根火柴的游戏者胜利。

    本题的游戏稍微有些不同:在第一个回合中,第一个游戏者可以直接拿走若干个整堆的火柴。可以一堆都不拿,但不可以全部拿走。第二回合也一样,第二个游戏者也有这样一次机会。从第三个回合(又轮到第一个游戏者)开始,规则和Nim游戏一样。

    如果你先拿,怎样才能保证获胜?如果可以获胜的话,还要让第一回合拿的火柴总数尽量小。

    输入输出格式

    输入格式:

    第一行为整数(k)。即火柴堆数。

    第二行包含(k)个不超过(10^9)的正整数,即各堆的火柴个数。

    输出格式:

    输出第一回合拿的火柴数目的最小值。如果不能保证取胜,输出(-1)


    你不能让对面拿的使(SG)异或和为(0)

    然后发现让整个异或集合线性无关就行了,就是形成一组基底。

    然后我就傻了..居然写了边交换边插入

    事实先排序就行了,从大的开始插入...


    Code:

    #include <cstdio>
    #include <algorithm>
    #define ll long long
    int n,a[105],base[32];
    ll ans;
    int Insert(int x)
    {
        for(int i=30;~i;i--)
            if(x>>i&1)
            {
                if(base[i]) x^=base[i];
                else {base[i]=x;return 1;}
            }
        return 0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        std::sort(a+1,a+1+n);
        for(int i=n;i;i--) ans=ans+(Insert(a[i])?0:a[i]);
        printf("%lld
    ",ans);
        return 0;
    }
    

    2018.12.23

  • 相关阅读:
    1265 四点共面
    1298 圆与三角形
    1264 线段相交
    1185 威佐夫游戏 V2
    1183 编辑距离
    1089 最长回文子串
    HTML5 boilerplate 笔记(转)
    Grunt上手指南(转)
    RequireJS 2.0初探
    RequireJS学习笔记
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10164988.html
Copyright © 2011-2022 走看看