ZOJ 3591 Nim (连续子序列异或和)

来源:互联网 发布:wps mac 免费完整版 编辑:程序博客网 时间:2024/05/16 12:37

题目链接:ZOJ 3591 Nim

题意:根据题目给出的代码得到n堆石头的各自的数量,求先手选出连续的若干堆并且必胜的方法数。(比如:3,1,1 每堆石头数是1,1,1.先手选出(1),(1),(1),(1,1,1) 这四种方案是必胜的,所以答案是4)

思路:在n堆取石头首先想到的是Nim博弈,连续的若干堆,即求连续子序列异或和为0的数量m,n*(n+1)/2-m就是答案

(Nim博弈结论,a1,a2,a3……an,an-1,若a1^a2^a3^……^an^an-1=0先手必败 )

连续子序列异或和类似连续子序列和 详细请看:http://blog.csdn.net/u012377575/article/details/44906065



如有不妥之处,欢迎指正!


AC代码:

#include <stdio.h>#include <map>#include <algorithm>#include <string.h>#define LL long longusing namespace std;LL a[100010];LL sumXor[100010];map<LL,LL> vis;void getA(LL n,LL w,LL s){    LL i;    LL g=s;    for(i=0;i<n;i++){        a[i]=g;        if(a[i]==0){            a[i]=g=w;        }        if(g%2==0) g=g/2;        else g=(g/2)^w;    }}int main(){    int t,i;    LL n,w,s;    scanf("%d",&t);    while(t--){        vis.clear();        memset(sumXor,0,sizeof sumXor);        scanf("%lld %lld %lld",&n,&s,&w);        getA(n,w,s);        LL ans=0;        sumXor[0]=a[0];        for(i=1;i<n;i++)            sumXor[i]=sumXor[i-1]^a[i];        LL u;        vis[0]=1;        for(i=0;i<n;i++){            u=sumXor[i];            ans+=vis[u];            vis[u]++;        }        printf("%lld\n",n*(n+1)/2-ans);    }    return 0;}



0 0
原创粉丝点击