HDU 5785 A Simple Nim(组合游戏,sg函数)

题目链接

是hiho的一道姊妹题目。知道了sg定理,及其函数的计算方式后,对于本题目。
对于某一堆,每次有2个操作:
A) 要么分堆,对于状态k,分为3堆,i,j,k-i-j(i,j>0),那么状态的转移就是所有的可能分堆情况
B) 不分堆,就是普通的NIM游戏,那么状态k,可以转移到0到k-1的状态

综上,sg[k]=mex{sg[0],sg[i],sg[i] xor sg[j] xor sg[k-i-j] | i>0,j>0,k-i-j>0}
最后的答案就是每一堆的sg函数的异或和
打表找一下规律

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<string>
#include<set>
#include<cstdlib>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define LL long long
#define pb push_back

#define For(i,j,k) for(int i=(j);i<k;i++)
#define lowbit(i) (i&(-i))
#define _(x) printf("%d\n",x)

const int maxn = 15+200;
const int inf  = 1 << 28;

//打表计算sg的代码
set<int> s;
int sg[maxn];
int grundy(int k){
    s.clear();
    sg[0]=0;
    s.insert(sg[0]);

    for(int i=1;i<k;i++){
        for(int j=1;j+i<k;j++)
        s.insert(sg[i]^(sg[j]^sg[k-i-j]));
        s.insert(sg[i]);
    }
    int ans = 0;
    while(s.count(ans))ans++;
    sg[k]=ans;
    return ans;
}


int main(){
    /*int n=27;
    for(int i=1;i<=n;i++){
        printf("%2d ",i);
    }
    puts("");
    for(int i=1;i<=n;i++){
        int t = grundy(i);
        printf("%2d ",t);
    }*/
    int T;scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        LL ans=0;
        for(int i=0;i<n;i++){
            LL x;scanf("%lld",&x);
            if((x-7)%8==0)ans^=(x+1);
            else if((x-8)%8==0)ans^=(x-1);
            else ans^=x;
        }
        printf("%s\n",ans?"First player wins.":"Second player wins.");

    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值