hdu 3032 Nim or not Nim? (sg函数打表找规律)

题意:有N堆石子,每堆有s[i]个,Alice和Bob两人轮流取石子,可以从一堆中取任意多的石子,也可以把一堆石子分成两小堆

       Alice先取,问谁能获胜

思路:首先观察这道题的数据范围  1 ≤ N ≤ 10^6, 1 ≤ 【Si】 ≤ 2^31 - 1,很明显数据量太大,所以只能通过打表找规律

        打表后发现,如果x%4==0 sg[x]=x-1 ;如果 x%4==3 sg[x]=x+1;如果 其他情况 sg[x]=x;

代码:

打表代码:

#include <iostream>
#include <cstring>
using namespace std;

int sg[1000];

int get(int n)
{
    if(n<0) return 0;
    if(sg[n]!=-1) return sg[n];
    bool visit[1005];
    memset(visit,false,sizeof(visit));
    for(int i=1;i<=n/2;i++)
      visit[get(i)^get(n-i)]=true;
    for(int i=1;i<=n;i++)
    {
        visit[get(n-i)]=true;
    }
    int k;
    for(int i=0;i<=1000;i++)
    {
        if(visit[i]==false)
        {
           return sg[n]=i;
        }
    }
}


int main()
{
    memset(sg,-1,sizeof(sg));
    sg[0]=0;sg[1]=1;
    for(int i=2;i<=100;i++)
    {
        get(i);
    }
    for(int i=1;i<=100;i++)
    cout<<i<<"  "<<sg[i]<<endl;
    return 0;
}

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;


int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,x,ans=0;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            if(x%4==0)
             ans=ans^(x-1);
            else if(x%4==3)
             ans=ans^(x+1);
            else
             ans=ans^x;
        }
        if(ans)
        cout<<"Alice"<<endl;
        else
        cout<<"Bob"<<endl;
    }
    return 0;
}

 

posted @ 2016-12-14 13:59  simpleknight  阅读(168)  评论(0编辑  收藏  举报