A Simple Nim (SG函数+打表找规律)

原题:hdu 5795

题意:在Nim游戏的基础上添加一个操作——可以将一堆分成三堆非空的小堆

解析:

因为数据比较大,所以不能直接打表交上去

打小范围内的SG表,拿操作就是直接减,分堆操作可以这么想,因为最终多堆的SG值要异或在一起,所以我们分成三堆相当于这三堆的SG值的异或,最后打表找出规律为:

s g ( 8 k ) = 8 k 1 , s g ( 8 k 1 ) = 8 k , s g ( o t h e r i ) = i

代码:

#include<bits/stdc++.h>
using namespace std;

int read(){
    int t;scanf("%d",&t);
    return t;
}

/*打表部分
int sg[10009];
bool vis[10000];

void init(){

    memset(sg,0,sizeof(sg));
    for(int i=1;i<=201;i++){
        memset(vis,0,sizeof(vis));

        for(int j=0;j<i;j++){
            vis[sg[j]]=1;//维护mex,不是vis状态而是状态的SG值
        }
        for(int j=1;j<i;j++){
            for(int k=1;k<i;k++){
                int y=i-j-k;
                if(y>0)vis[sg[j]^sg[k]^sg[y]]=1;
            }
        }


        for(int j=0;;j++){//找最小
            if(!vis[j]){sg[i]=j;break;}
        }
    }
}
*/
int sg(int a){
    if(a%8==0)return a-1;
    if((a+1)%8==0)return a+1;
    return a;
}

int main(){/*
    init();
    for(int i=0;i<=200;i++)printf("sg[%d]= %d\n",i,sg[i]);*/

    int t=read();
    while(t--){
        int n=read();
        int ans=0;
        while(n--){int tmp=read();ans^=sg(tmp);}
        if(!ans)printf("Second player wins.\n");
        else printf("First player wins.\n");
    }
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/82465999