HDU-1848 Fibonacci again and again(sg函数+可恶的bug)

题目链接

题意:两人轮流取石子,总共三堆石子数量分别为n,m,p,每次取石子只能取斐波拉契数字数量,在最优状态下谁先取完。

思路:很明显可以将每堆石子看成一个节点,因此答案为sg[n]^sg[m]^sg[m]的值如果为0,后手获胜,反之先手获胜。

因为大小只有1000,可以直接去推sg函数求解。

可恶的bug:判断语句中写成SG[n]^SG[m]^SG[p]!=0,!比^的优先级高,应该写成(SG[n]^SG[m]^SG[p])!=0。谨记!

对于学习sg函数推荐两篇比较好的博客:

https://www.cnblogs.com/Mathics/p/3948482.html

https://www.cnblogs.com/ecjtuacm-873284962/p/6921829.html(推荐先看,了解大概)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int f[100];
int SG[1010];
int vis[1010];
int main()
{
    int m,n,p;
    f[1]=1;
    f[2]=1;
    int len=0;
    for(int i=3;i<100;i++)
    {
        f[i]=f[i-1]+f[i-2];
        if(f[i]>1000)
        {
            len=i;
            break;
        }
    }
    //printf("%d\n",len);
    SG[0]=0;
    for(int i=1;i<=1000;i++)
    {
        memset(vis,0,sizeof(vis));
        for(int j=2;j<len;j++)
        {
            if(f[j]<=i)
            {
                vis[SG[i-f[j]]]=1;
            }
            else
            {
                break;
            }
        }
        for(int j=0;;j++)
        {
            if(!vis[j])
            {
                SG[i]=j;
                break;
            }
        }
    }
    while(scanf("%d%d%d",&n,&m,&p)!=EOF)
    {
        if(m==0&&n==0&&p==0)
        {
            break;
        }
        if((SG[n]^SG[m]^SG[p])!=0)
        {
            printf("Fibo\n");
        }
        else
        {
            printf("Nacci\n");
        }
    }
}

 

posted @ 2020-10-06 21:46  Ldler  Views(104)  Comments(0Edit  收藏  举报