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);
    }
}

 

posted @ 2020-05-10 11:41  zlc0405  阅读(107)  评论(0编辑  收藏  举报