HDU 3032 nim or not nim(sg函数打表)

题意:
有n堆石子,每次可以从一堆石子里面取至少1个石子,或者将一堆石子分为两堆,问先手必赢还是必输
题解:
用SG函数打表找规律,sg[0]=0;sg[1]=1;当有2个石子时,经过操作后可以变成0个,1个,或者(1,1)这三种状态,。。。所有堆的石子个数的sg异或为0则必败。反之必胜。
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int MAXN=1e6+5;
int vis[1000];
int sg[1000]; 
void getsg()
{
    
    
    sg[0]=0;
    sg[1]=1;
    for(int i=2;i<=100;i++)
    {
    
    
        memset(vis,0,sizeof vis);
        for(int j=1;j<=i;j++)
        {
    
    
            vis[sg[i-j]]=1;
        }
        for(int j=1;j<=i-1;j++)
        {
    
    
            vis[sg[j]^sg[i-j]]=1;
        }
        for(int j=0;;j++)
        {
    
    
            if(vis[j]==0)
            {
    
    
                sg[i]=j;
                break;
            }
        }
    }
}
int main()
{
    
    
    /*getsg();
    for(int i=1;i<=50;i++)
    {
        cout<<i<<" "<<sg[i]<<endl;
    }*/
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        int n;
        scanf("%d",&n);
        int x;
        int ans=0;
        for(int i=1;i<=n;i++)
        {
    
    
            scanf("%d",&x);
            if(x%4==0) ans^=(x-1);
            else if(x%4==3) ans^=(x+1);
            else ans^=x;
        }
        if(ans==0) printf("Bob\n");
        else printf("Alice\n");
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/108749885