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 }