首页 > 其他 > 详细

[CQOI2013]新Nim游戏

时间:2019-05-14 21:34:32      阅读:144      评论:0      收藏:0      [点我收藏+]

洛咕

本题和[BJWC2011]元素简直神似,可以说是双倍经验了.

题意:第一轮为自定义游戏,可以取走若干堆石子,也可以不取.第二轮开始为传统Nim游戏.在保证先手必胜的情况下,使得第一回合拿的火柴总数尽量小.

分析:首先我们只考虑如何保证先手必胜,因为从第二轮开始就是传统的Nim游戏了,而Nim游戏先手必胜当且仅当异或和不为0,所以我们要在第一轮构造一个局,使得第二轮一开始就是先手必胜的局面,即异或和不为0.

对于异或和不为0问题,考虑线性基.因为线性基的性质之一就是异或和不为零,所以我们只要构造出这n个数的线性基就行了,n个数中不能放入线性基的数就是我们第一轮一开始就要拿走的.

因为题目要保证第一回合拿的数尽量小,\(sort\)排序就好了,我们对于这n个数,从大到小构建线性基.

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
int a[105],p[32];
inline bool get_LB(int n){
    for(int i=31;i>=0;i--)
        if(n>>i){
            if(!p[i]){p[i]=n;break;}
            else n^=p[i];
        }
    return n>0;
}
int main(){
    LL ans=0;int n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    sort(a+1,a+n+1);
    for(int i=n;i;i--)
        if(!get_LB(a[i]))ans+=a[i];
    printf("%lld\n",ans);
    return 0;
}

[CQOI2013]新Nim游戏

原文:https://www.cnblogs.com/PPXppx/p/10864444.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!