ZOJ3591 Nim

来源:互联网 发布:linux下编译qt5.7源码 编辑:程序博客网 时间:2024/05/29 02:53

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4675


大意:根据题目中给的函数生成一串正整数作为若干石子堆的个数,然后选取若干连续的石子堆玩NIM游戏,求有多少种选法使得先手必胜。


要求被选中的这若干个连续的数字异或为1,也就是说,Cn,2减去某段异或为0的情况个数即为答案。用b[i]表示从a[1]到a[i]的异或结果,则若b[j]=b[k],则a[j+1]到a[k]的异或结果必为0。将计算好的b数组排序,然后处理值相同的部分。


#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<vector>#include<algorithm>#include<map>using namespace std;#define N 100005int a[N],b[N];int main(){    //freopen("a","r",stdin);    int t,i;    long long n,s,w,sum,sum1;    cin>>t;    for (int k=1;k<=t;k++)    {        cin>>n>>s>>w;        sum=0;        sum1=0;        int g = s;        for (i=1; 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;        }        b[1]=a[1];        for (i=2;i<=n;i++)        {            b[i]=b[i-1]^a[i];            if (b[i]==0) sum1++;        }        sort(b+1,b+n+1);        int m=1;        for (i=2;i<=n;i++)        {            if (b[i]==b[i-1]) m++;            else            {                sum1+=(m-1)*m/2;                m=1;            }        }        sum1+=(m-1)*m/2;//处理一下最后几个相同的元素        sum=(n+1)*n/2-sum1;        printf("%lld\n",sum);    }    return 0;}


原创粉丝点击