[CQOI2013]新Nim游戏
首先,我们可以发现,只要在第一次我们自己拿的时候,使得对方无论怎么拿都不能使异或和为0即可获胜。 考虑到线性基任意一个非空子集的异或和不为0,那么我们只要给对方留下一个线性基即可。所以先手必胜。
之后考虑怎么让代价最小。这个也很简单,我们仿照上一道题目的做法,优先插入权值大的堆。每次判断一下这个是否会被线性基异或出来,如果能的话,那么就要选取他。
看一下代码。
#include <bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
typedef long long ll;
ll k,a[105],p[30],ans;
bool pd(ll x)
{
ll b = x;
per(i,60,0)
{
if((x ^ p[i]) < x) x ^= p[i];
if(!x) {ans += b;return 1;}
}
return 0;
}
void insert(ll x)
{
per(i,60,0)
{
if(!((x >> i) & 1)) continue;
if(!p[i]) {p[i] = x; break;}
x ^= p[i];
}
}
int main()
{
scanf("%lld",&k);
rep(i,1,k) scanf("%lld",&a[i]);
sort(a+1,a+1+k);
per(i,k,1) if(!pd(a[i])) insert(a[i]);
printf("%lld\n",ans);
return 0;
}
当你意识到,每个上一秒都成为永恒。