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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章