zoukankan      html  css  js  c++  java
  • [CQOI2013]新Nim游戏

    [CQOI2013]新Nim游戏

    在Nim游戏中,限定第一回合玩家可以拿走任几堆石子,但不能全部拿完,同样第二回合选手进行同样操作,接下来的回合同Nim游戏操作,询问先手是否必胜所拿走的最少的石子。

    不难得知应该要用Nim游戏的结论,自然想到暴力建SG函数,但是注意问题只有前两个回合特殊,根据Nim定理,换一种解释即选出最多的数构成一个集合,使其任意子集异或和不为0。

    异或和问题,考虑线性基,现在我们有了如何判断异或和是否为0的工具,经验告诉我们自由选择一般不能递推,于是考虑贪心,从大到小选择,如果能够加入线性基,就选择即可,正确性证明如下。


    证明:

    假设选到第i个数(a_i),前i个数已经选到最优情况,如果不是最优的情况,必然至少存在(a_j,a_k)使其和大于(a_i),并且因为(a_i)的存在,不能加入线性基,但是(a_i)在线性基中只占一个二进制位,而因为其存在而不能选这两个数,意味着这两个数加入线性基时必然也占这一个二进制位,而位置只有一个,故显然它们会互斥,于是矛盾,得证。


    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    struct linear_base{
        int base[32];
        il bool insert(int x){
            ri int i;
            for(i=31;i>=0;--i)
                if(x>>i){
                    if(base[i])x^=base[i];
                    else return base[i]=x;
                }return false;
        }
    }B;int a[101];
    il void read(int&);
    int main(){
        int k,i;ll ans(0);read(k);
        for(i=1;i<=k;++i)read(a[i]);sort(a+1,a+k+1);
        for(i=k;i;--i)if(!B.insert(a[i]))ans+=a[i];
        printf("%lld",ans);
        return 0;
    }
    il void read(int &x){
        x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    
  • 相关阅读:
    themes、skins
    使用GreyBox实现Ajax模式窗口
    .net最小化到系统托盘
    asp.net自定义控件
    [转]SQL函数的简短说明
    prototype1.4 和1.5
    [转]Oracle PL/SQL 编程手册(SQL大全)
    更新同一张表中的数据的方法
    js中eval()的作用
    asp.net中的中文和特殊字符的处理方式!
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10859551.html
Copyright © 2011-2022 走看看