洛谷P4301 [CQOI2013]新Nim游戏(线性基)

传送门

后手在什么时候能够获胜呢?只有在他能构造出一个子集的异或和为0时(这个应该是nim博弈的结论了吧)

那么为了必胜,我们就要取到没有子集异或和为0为止

那就是构造一个线性无关,那么构造线性基即可

然后还有一个问题就是石子要取得最小,那么就是留下来的要最大,就是被加进线性基中的要最大

考虑贪心,从大到小取石头,如果不能被线性基中的数表示那么就加入线性基,否则这堆石子就要取走

据说贪心的证明得用拟阵,我还是不会

 1 //minamoto
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define ll long long
 5 using namespace std;
 6 const int N=105;
 7 ll b[65],a[N],ans;int n;
 8 inline void insert(ll x){
 9     for(int i=63;i>=0;--i)
10     if(x>>i&1){
11         if(!b[i]) return (void)(b[i]=x);
12         x^=b[i];
13     }
14 }
15 inline bool find(ll x){
16     for(int i=63;i>=0;--i)
17     if(x>>i&1){
18         if(!b[i]) break;
19         x^=b[i];
20     }
21     return x;
22 }
23 int main(){
24     scanf("%d",&n);
25     for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
26     sort(a+1,a+1+n);
27     for(int i=n;i;--i)
28     if(find(a[i])) insert(a[i]);
29     else ans+=a[i];
30     printf("%lld\n",ans);
31     return 0;
32 }

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9720762.html