A Simple Nim(HDU 5795 A)

SG函数应用模板题,但还是想写一下(SG入门从此起步)
这里写图片描述
大意是:有很多堆糖果,每个人可以在一堆取走任意多个糖果,或者将其分成3个非空堆。最后取走为胜,问先手胜还是后手。
主要在用SG打表上,用SG输出每个值的mex,从中找规律。

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

///题目中要求的是可以分解为三堆,或者可以取走任意个
int sg[maxn];
bool vis[maxn];
int makesg(int num)
{
    if(sg[num]!=-1)
        return sg[num];
    memset(vis,0,sizeof(vis));
    for(int i=1;i<num;i++)///sg的值小于num的值
    {
        int a=makesg(i);
        for(int j=1;j<num-i;j++)
        {
            int b=num-i-j;///根据题目要求将一堆分成三堆
            int c=makesg(j);
            int d=makesg(b);
            int sgg=a^d^c;
            vis[sgg]=1;///这个子状态已经找过了
        }
        vis[a]=1;
    }
    vis[0]=1;
    for(int i=1;;i++)
    {
        if(!vis[i]) return i;///一直未出现的即是mes{}中未出现的最小的非负整数
    }
}
int main()
{
    memset(sg,-1,sizeof(sg));
    for(int i=1;i<=100;i++)
    {
        sg[i]=makesg(i);
    }
    for(int i=1;i<=100;i++)
    {
        printf("sg[%d]=%d\n",i,sg[i]);
    }
}

通过打表可知:8的倍数和7的倍数的SG值会互换,其他的SG值和本值相同,故AC代码如下:

#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long ll;
ll T;
ll x;
ll N;
ll sg(ll x)
{
    if(x%8==0)return x-1;
    if(x%8==7)return x+1;
    return x;
}
int main()
{
     scanf("%I64d",&T);
     while(T--)
     {
        scanf("%I64d",&N);
        ll ans=0;
        for(int i=0;i<N;i++)
        {
             scanf("%I64d",&x);
             ans^=sg(x);
        }
        if(ans)printf("First player wins.\n");
        else printf("Second player wins.\n");

     }


    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值