zoukankan      html  css  js  c++  java
  • 【bzoj3105】新Nim游戏

    Portal--> bzoj3105 新Nim游戏

    Solution

      转化一下问题

      首先看一下原来的Nim游戏,先手必胜的条件是:每堆数量的异或和不为(0)

      所以在新的游戏中,如果要保证自己(先手)有必胜策略的话,那必须要保证到一开始先手拿走若干堆之后,后手无法拿走若干堆使得剩下每堆的数量异或和为(0),也就是说我们要留下的应该是一个极大线性无关组

      线性无关组这个的话我们可以通过线性基解决,具体的话就是如果(insert)完了之后这个数被变成了(0),那么说明这个数和线性基里面的数线性相关

      容易注意到(insert)的顺序会有影响,那么现在的问题就是,应该选取哪些数作为线性基(或者说应该按照什么顺序把那堆数插到线性基里)

      先把结论摆出来:实际上只要按照从大到小的顺序贪心地加就好了

      为什么可以贪心呢?

      

      这里需要借助一个很神奇的东西:Portal-->拟阵

      

    ​  我们设(n)个火柴堆的数目为集合(S),如果(S)的某个子集(R)不存在任何一个非空子集异或和为(0),那么(Rin I)

      接下来我们来证明一下(M=(S,I))是一个拟阵

      1、首先(S)肯定是一个有限集

      2、遗传性:设(Ain I),则由定义可知(A)不存在任何一个非空子集满足异或和为(0),所以对于任意(B subseteq A)(B)都满足不存在任何一个非空子集异或和为(0)(因为(B)的子集也是(A)的子集),所以(Bin I),所以(I)是遗传的

      3、交换性质:设(,A,Bin I),且(|B|>|A|),我们现在要证明(exists xin B-A)使得(Acup{x}in I),这里考虑用反证法:假设对于(forall xin B-A)均有(Acup {x} otin I),则(B-A)中的元素均可以由(A)的某个子集的异或和表示,因此我们可以得到结论(B)中的所有元素均可以由(A)的某个子集的异或和来表示。但是这与我们前面的假设(|B|>|A|)是矛盾的,所以假设不成立,得证。

    ​  我们将(M=(S,I))看成一个带权拟阵,每个(S)中的元素的权值就是对应的堆中火柴的数量,那么运用贪心算法我们就可以在带权拟阵中找出权值最大的基

      所以就能直接用贪心做啦

    ​   

      代码大概长这个样子:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int MAXN=110,UP=30;
    int a[MAXN];
    int n,m;
    ll ans;
    namespace xxj{
        int a[UP+1];
        bool insert(int x){
            for (int i=UP;i>=0;--i)
                if (x&(1<<i)){
                    if (!a[i]){
                        a[i]=x;
                        break;
                    }
                    x^=a[i];
                }
            return x;
        }
    }
     
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("a.in","r",stdin);
    #endif
        scanf("%d",&n);
        for (int i=1;i<=n;++i) scanf("%d",a+i);
        sort(a+1,a+1+n);
        ans=0;
        for (int i=n;i>=1;--i)
            if (!xxj::insert(a[i])) 
                ans+=a[i];
        printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    flash盖住层的解决办法
    编译Chromium
    关于Ubuntu上的版本依赖问题
    GridBagLayout
    使用JList遇到的奇怪问题
    Swing常用整理
    Swing中改变Table的column大小
    SwingUtilities.invokeLater
    git常用命令
    小马过河(bupt 311)
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9218187.html
Copyright © 2011-2022 走看看