• [CQOI2013]新Nim游戏(线性基)


    P4301 [CQOI2013]新Nim游戏

    题目描述

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

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

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

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制

    6
    5 5 6 6 5 5

    输出样例#1: 复制

    21

    说明

    k<=100



    题解

    该写什么呢。。。
    Nim游戏的必胜定理
    (A_1,A_2,A_3...,A_n)(xor) 和不为0,那么一定有东西可取,且让下一个人取时 (xor) 和为0时。为必胜状态。


    则我们只需要让第一次第一个人取走的石子不能让下一次取石子的人可以取成 (xor) 为0的值就好了。
    那么我们想到了什么?线性基。
    线性基内的数是肯定不会被 (xor) 为0的。我们只需要把那些无法第一次放入线性基的数加入答案即可。
    而数值可以从大到小排序,那么我们可以优先不取大数而取小数了。



    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll ans,n;
    ll sum[101],ch[101],b[101];
    ll read()
    {
        ll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    bool cmp(ll a,ll b){
        return a>b;
    }
    
    void update(){
        for(int i=1;i<=n;i++){
            int x=ch[i];
            for(int j=60;j>=0;j--){
                if(sum[j]&ch[i]){
                    if(b[j])ch[i]^=b[j];
                    else {
                        b[j]=ch[i];break;
                    }
                }
            }
            if(!ch[i])ans+=x;
        }
    }
    
    int main()
    {
        n=read();
        sum[0]=1;for(int i=1;i<=60;i++)sum[i]=sum[i-1]*2;
        for(int i=1;i<=n;i++)ch[i]=read();
        sort(ch+1,ch+n+1,cmp);
        update();
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    【大数据学习与分享】技术干货合集
    K8S集群搭建
    字节跳动面试难吗,应该如何应对?(含内推方式)
    我的新书《C++服务器开发精髓》终于出版啦
    同事内推的那位Linux C/C++后端开发同学面试没过......
    死磕hyperledger fabric源码|Order节点概述
    死磕以太坊源码分析之EVM如何调用ABI编码的外部方法
    死磕以太坊源码分析之EVM动态数据类型
    死磕以太坊源码分析之EVM固定长度数据类型表示
    死磕以太坊源码分析之EVM指令集
  • 原文地址:https://www.cnblogs.com/hhh1109/p/9348949.html
Copyright © 2020-2023  润新知