2020ICPC 博弈题 纳新一百的石子游戏

https://ac.nowcoder.com/acm/contest/4010/C

这道题为尼姆博弈的其中一种裸类型;

要求求出前(1~n)堆的必胜方案。

对于这种类型,假如我们现在就前k堆,那么我们先异或出前k堆的异或值;

然后再对k堆中的每一项进行下列操作: tmp=sum^a[i] ,假如总的异或值异或第i项得出的值小于a[i];则方案数+1;

但是这种方法复杂度为n^2;

所以我们需要将前k堆每一项值都用二进制保留下来;

然后枚举到总的异或值的最高位的下标,然后在该下标所保存有多少个数,即为多少种方案;

为什么呢,因为假如总的异或值能够异或到这一位的话,证明该总的异或值与该下标保存着的任意一个a[i]异或,都会小于a[i],因为两者该为都为1;

总的异或值异或之后就变为0,所以肯定比a[i]小;

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+1;
 4 typedef long long ll;
 5 ll a[maxn],num[maxn],sum=0;
 6 int main()
 7 {
 8     int n;
 9     scanf("%d",&n);
10     for(int i=1;i<=n;++i){
11         scanf("%lld",&a[i]);
12         sum^=a[i];
13         for(int j=0;j<62;++j){
14             if((a[i]>>j)&1) num[j]++;
15         }
16         if(sum==0){
17             printf("0\n");
18             continue;
19         }
20         ll t=sum,cnt=-1;
21         while(t) cnt++,t>>=1;
22         printf("%lld\n",num[cnt]);
23     }
24     return 0;
25 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/12292639.html