• 题解 P4301 [CQOI2013] 新Nim游戏


    P4301 [CQOI2013] 新Nim游戏

    先提一下 Nim 游戏:

    有多堆石子,双方每次可以在一堆里取任意多的火柴,先手必胜当且仅当所有堆的石子数异或和等于 (0)

    我们现在的目标就是拿走几堆火柴,让对面拿走多少堆火柴都没有办法使得异或和为 (0) (不能一次性拿完)。

    或者说,我们要选出一些数组成一个集合,这里面的数不能互相异或和表示出来。我们就能想到线性基了。

    我们求放进去的数的和最大的线性基。这样我们把其他的数取走就可以得到最小的方案。我们将火柴堆从大到小排序,动态维护一个线性基,每次试图向里面插入一个数,如果插入成功就将这个数统计到答案,并保留插入结果。最后再拿总数减去即可。

    由于我们肯定有必胜策略(一次性拿得只剩一堆),所以 (-1) 肯定是没分的。

    code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=1e3+10;
    
    int n;
    ll arr[N];
    
    bool insert(ll x)
    {
    	for(int i=63;i>=0;i--)
    	{
    		if(!(x>>i&1)) continue;
    		if(arr[i]) x^=arr[i];
    		else
    		{
    			for(int j=0;j<i;j++)
    				if(x>>j&1) x^=arr[i];
    			for(int j=i+1;j<n;j++)
    				if(arr[j]>>i&1) arr[j]^=x;
    			arr[i]=x;
    			return 1;
    		}
    	}
    	return 0;
    }
    ll poi[N];
    
    int main()
    {
    	scanf("%d",&n);
    	ll sum=0;
    	for(int i=1;i<=n;i++)
    		scanf("%lld",&poi[i]),sum+=poi[i];
    	sort(poi+1,poi+1+n,greater<long long>());
    	for(int i=1;i<=n;i++)
    		if(insert(poi[i])) sum-=poi[i];
    	printf("%lld",sum);
    }
    
  • 相关阅读:
    主元素 .
    Struts2中使用Session .
    不同的路径 .
    判断数独是否合法(LintCode) .
    最大子数组(LintCode) .
    不同的路径 II .
    删除元素(LintCode) .
    Hibernate 与Spring整合出现 hibernate.HibernateException: createCriteria is not valid without active transaction .
    子树(LintCode) .
    Surrounded Regions .
  • 原文地址:https://www.cnblogs.com/IzayoiMiku/p/15217520.html
Copyright © 2020-2023  润新知