zoukankan      html  css  js  c++  java
  • 【BZOJ3105】[CQOI2013] 新Nim游戏(贪心+线性基)

    点此看题面

    大致题意: 两个人玩新(Nim)游戏。一开始二人先各有一次拿走若干整堆石子的机会(可以不拿,但不能拿完),然后再进行普通的(Nim)游戏。问先手在保证胜利的情况下,一开始拿走的石子总数最小值。

    前言

    (Jan 29th)刷题计划(3/6),算法标签:贪心、线性基。

    遇上重题了(233)【BZOJ2460】 [BeiJing2011] 元素

    双倍经验

    做这道题之前,可以先去看一看另一道题:【BZOJ2460】 [BeiJing2011] 元素

    回来看这道题,(Nim)游戏有一个基本结论:当各堆石子数异或值不为(0)时,先手必胜。

    也就是说,先手在拿走若干整堆石子后,要让后手无论如何拿去剩下的石子,都无法使各堆石子数异或值为(0)

    拿去最少,就是留下最多。于是题目就被转化为:选出最多的石子,使得这些石子堆不存在一个子集使得子集中各堆石子个数异或和为(0)

    这样一来就和上面给出的那道题完全一致了,直接按照那道题的做法,贪心+线性基即可。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100
    #define LV 32
    #define LL long long
    using namespace std;
    int n,s[N+5],v[N+5];
    I bool Ins(RI x) {for(RI i=LV;~i;--i) if((x>>i)&1) {if(!v[i]) return v[i]=x;else x^=v[i];}return 0;}//插入线性基
    int main()
    {
    	RI i;LL t=0;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",s+i),t+=s[i];//统计石子总数
    	for(sort(s+1,s+n+1),i=n;i;--i) Ins(s[i])&&(t-=s[i]);return printf("%lld",t),0;//从大到小枚举,能留下就留下
    }
    
  • 相关阅读:
    hdoj 2586 How far away?(最近公共祖先)
    poj 1330 A-Nearest Common Ancestors
    心形图
    B1928 日期差值
    B1022 D进制的A+B
    B1009 说反话
    hihocoder 1498 签到
    51Nod 1082 与7无关的数
    51Nod 1015 水仙花数
    51Nod 1283 最小周长
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3105.html
Copyright © 2011-2022 走看看