zoukankan      html  css  js  c++  java
  • 【BZOJ3105】新Nim游戏(CQOI2013)-博弈论+异或线性基+贪心

    测试地址:新Nim游戏
    做法:本题需要用到博弈论+异或线性基+贪心。
    首先根据博弈论的基本知识,标准的Nim游戏中,只要所有火柴堆内的火柴数目的异或值为0,那么先手必败,否则先手必胜。而这个新的游戏在经过前两轮后就是一个由我们先手的标准Nim游戏,那么后手为了胜利,必然会留下若干堆火柴,使得它们的异或值为0,而我们为了胜利,就不能提供后手这个机会,那么我们就要使得我们选完后,留下的火柴堆不存在一个子集,使得子集内火柴数的异或和为0,这就等价于求一个线性无关组。又因为我们要求取走的火柴数最小,所以就是要求留下的火柴数尽量多,用类似BZOJ2460的贪心方法做即可。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxbit=31;
    int n,b[50];
    ll ans=0;
    struct forsort
    {
        int a,b;
    }q[110];
    
    bool cmp(forsort a,forsort b)
    {
        return a.b>b.b;
    }
    
    void work()
    {
        for(int i=1;i<=n;i++)
            for(int j=maxbit;j>=0;j--)
                if ((q[i].a>>j)&1)
                {
                    if (b[j]) q[i].a^=b[j];
                    else
                    {
                        b[j]=q[i].a;
                        ans-=(ll)q[i].b;
                        for(int k=0;k<j;k++)
                            if (b[k]&&((b[j]>>k)&1)) b[j]^=b[k];
                        for(int k=j+1;k<=maxbit;k++)
                            if ((b[k]>>j)&1) b[k]^=b[j];
                        break;
                    }
                }
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&q[i].a);
            ans+=(ll)q[i].a;
            q[i].b=q[i].a;
        }
    
        sort(q+1,q+n+1,cmp);
        work();
        printf("%lld",ans);
    
        return 0;
    }
  • 相关阅读:
    一些业内有名的网站收集
    WCF重载
    FCKEditor fckconfig.js配置,添加字体和大小 附:中文字体乱码问题解决
    查询第几条到第几条的数据的SQL语句
    SPOJ 9939 Eliminate the Conflict
    UVA 10534 Wavio Sequence
    HDU 3474 Necklace
    POJ 2823 Sliding Window
    UVA 437 The Tower of Babylon
    UVA 825 Walking on the Safe Side
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793500.html
Copyright © 2011-2022 走看看