p4301 [CQOI2013]新Nim游戏

传送门

分析

通过nim游戏我们可以知道我们现在的任务就是通过两轮之后使得剩余的几堆异或和为非0数

所以我们只需要在第一步使得剩余集合的任意非空子集的异或和非0即可

于是我们考虑线性基

我们知道线性基所选数会使总和最大且任意非空子集的异或和非0

于是跑线性基即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
long long a[110],n,Ans,belong[110];
inline bool cmp(long long x,long long y){return x>y;}
inline void work(){
    long long i,j,k;
    for(i=1;i<=n;i++){
      k=a[i];
      for(j=45;j>=0;j--)
        if((1<<j)&a[i]){
          if(!belong[j]){
              belong[j]=a[i];
              break;
          }
          a[i]^=belong[j];
        }
      if(!a[i])Ans+=k;
    }
}
int main(){
    long long i,j,k;
    scanf("%lld",&n);
    for(i=1;i<=n;i++)scanf("%lld",&a[i]);
    sort(a+1,a+n+1,cmp);
    work();
    printf("%lld\n",Ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/10130885.html