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;
    }
  • 相关阅读:
    selenium 详解
    验证码破解
    Jupyter Notebook 安装
    分布式
    selenium +scrapy 实现网易新闻
    scrapy 反扒措施_2
    Typora简单使用
    20155215 2016-2017-2 《Java程序设计》第4周学习总结
    20155215 2016-2017-2 《Java程序设计》第3周学习总结
    20155215 2006-2007-2 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793500.html
Copyright © 2011-2022 走看看