ZOJ3591 Nim(博弈论)
裂开,周赛对博弈论一无所知。。。
/* * zoj3591 Nim * 题意: * 就是,给几个数,可以求出每堆石子数,要求有多少个连续段可以,有必胜的把握! * 如果枚举的做法,肯定会超时,做法是先求出必败的个数,再用总数相减。 * 用c[i]表示前i项的异或和,那么如果c[i]=c[j],那么i和j之间的一段异或和一定是0。 * 如果把所有的相等的找在一起,再一起求组合,就可以。 * */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+100; int a[maxn]; int c[maxn]; int N,S,W; int main () { int T; scanf("%d",&T); while (T--) { scanf("%d%d%d",&N,&S,&W); int g=S; ll ans=0; for (int i=0;i<N;i++) { a[i]=g; if (a[i]==0) a[i]=g=W; if (g%2==0) g/=2; else g=(g/2)^W; } c[0]=0; for (int i=1;i<=N;i++) c[i]=c[i-1]^a[i-1]; sort(c+1,c+N+1); ans=((ll)(N+1))*((ll)N)/2; ll len=1; for (int i=2;i<=N;i++) { if (c[i]!=c[i-1]) { if (c[i-1]==0) ans-=len; ans-=len*(len-1)/2; len=1; } else len++; } ans-=len*(len-1)/2; printf("%lld\n",ans); } }