• hdu 1848 sg——dfs&&打表双实现


    Fibonacci again and again

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 6363    Accepted Submission(s): 2646


    Problem Description
    任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:
    F(1)=1;
    F(2)=2;
    F(n)=F(n-1)+F(n-2)(n>=3);
    所以,1,2,3,5,8,13……就是菲波那契数列。
    在HDOJ上有不少相关的题目,比如1005 Fibonacci again就是曾经的浙江省赛题。
    今天,又一个关于Fibonacci的题目出现了,它是一个小游戏,定义如下:
    1、  这是一个二人游戏;
    2、  一共有3堆石子,数量分别是m, n, p个;
    3、  两人轮流走;
    4、  每走一步可以选择任意一堆石子,然后取走f个;
    5、  f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
    6、  最先取光所有石子的人为胜者;

    假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。
     
    Input
    输入数据包含多个测试用例,每个测试用例占一行,包含3个整数m,n,p(1<=m,n,p<=1000)。
    m=n=p=0则表示输入结束。
     
    Output
    如果先手的人能赢,请输出“Fibo”,否则请输出“Nacci”,每个实例的输出占一行。
     
    Sample Input
    1 1 1 1 4 1 0 0 0
     
    Sample Output
    Fibo Nacci
     
    Author
    lcy
     
    由于本题n的范围为1000,所以时间复杂度不是很高
    下面两种方法的代码都可以过,,
    15086248 2015-10-12 19:11:07 Accepted 1848 0MS 1576K 1320 B G++ 牟柏旭
     
     1   //f[]:可以取走的石子个数
     2     //sg[]:0~n的SG函数值
     3     //Hash[]:mex{}
     4     #include<stdio.h>
     5     #include<string.h>
     6     #include<iostream>
     7     #include<algorithm>
     8     using namespace std;
     9     const int N=1005;
    10     const int K=20;
    11     int f[K],sg[N],Hash[N];
    12     int k;
    13     void getSG(int n)
    14     {
    15             memset(sg,0,sizeof(sg));
    16             for(int i=1; i<=n; i++) {
    17                     memset(Hash,0,sizeof(Hash));
    18                     for(int j=0; f[j]<=i && j < k; j++) //k是f[]的有效长度
    19                             Hash[sg[i-f[j]]]=1;
    20                     for(int j=0; ; j++) {   //求mes{}中未出现的最小的非负整数
    21                             if(Hash[j]==0) {
    22                                     sg[i]=j;
    23                                     break;
    24                             }
    25                     }
    26             }
    27     }
    28     int main(){
    29        int x1,x2,x3;
    30        f[0]=1;
    31        f[1]=1;
    32        for(int i=2;i<=16;i++)
    33         f[i]=f[i-1]+f[i-2];
    34         k=17;
    35        getSG(1000);
    36        while(scanf("%d%d%d",&x1,&x2,&x3)!=EOF){
    37           if(x1==0&&x2==0&&x3==0)
    38             break;
    39           int ans;
    40           ans=sg[x1]^sg[x2]^sg[x3];
    41           if(ans)
    42             printf("Fibo
    ");
    43           else
    44             printf("Nacci
    ");
    45 
    46        }
    47        return 0;
    48     }

    上面的打表的代码,下面附上dfs代码

    15087133 2015-10-12 20:11:06 Accepted 1848 109MS 1880K 1060 B C++ 牟柏旭
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    
    using namespace std;
    const int k=17;
    int s[18],sg[1001];
    int getsg(int m)
    {
        int hash[21]={0};
        int i;
        for(i=0;i<k;i++){
            if(m-s[i]<0)
                break;
            if(sg[m-s[i]]==-1)
                sg[m-s[i]]=getsg(m-s[i]);
            hash[sg[m-s[i]]]=1;
        }
        for(i=0;;i++)
            if(hash[i]==0)
                return i;
    
    
    }
    int main()
    {
        int x[5];
        s[0]=1;
        s[1]=1;
         for(int i=2;i<17;i++)
          s[i]=s[i-1]+s[i-2];
        while(scanf("%d%d%d",&x[1],&x[2],&x[3])!=EOF)
        {
            if(x[1]==0&&x[2]==0&&x[3]==0)
                break;
            int i;
    
            memset(sg,-1,sizeof(sg));
            sg[0]=0;
    
    
    
    
                int ans=0;
    
    
                for(int i=1;i<=3;i++){
                    if(sg[x[i]]==-1)
                        sg[x[i]]=getsg(x[i]);
                    ans^=sg[x[i]];
                }
                if(ans)
                    cout<<"Fibo"<<endl;
                else cout<<"Nacci"<<endl;
    
    
        }
        return 0;
    }
    15087680 2015-10-12 20:35:01 Accepted 1848 140MS 1772K 1384B C++ 牟柏旭
        #include<cstdio>
        #include<string.h>
        #include<iostream>
        #include<algorithm>
        using namespace std;
        const int  N=20;
        int knum;
        int si[N],sg[1010];
        int mex(int x)//求x的sg值(可作为模版应用)
        {
            if(sg[x]!=-1)
                 return sg[x];
            bool vis[N];
            memset(vis,false,sizeof(vis));
            for(int i=1;i<knum;i++)    {
                int temp=x-si[i];
                if(temp<0)
                break;
                sg[temp]=mex(temp);
                vis[sg[temp]]=true;
            }
            for(int i=0;i<17;i++)    {
                if(!vis[i])    {
                    sg[x]=i;
                    break;
                }
            }
            return sg[x];
        }
        int main()    {
    
    
    
            int x[5];
           
            while(scanf("%d%d%d",&x[1],&x[2],&x[3])!=EOF)   {
                     if(x[1]==0&&x[2]==0&&x[3]==0)
                    break;
                     si[0]=1;
            si[1]=1;
            for(int i=2;i<17;i++)
                si[i]=si[i-1]+si[i-2];
                knum=17;
                memset(sg,-1,sizeof(sg));
                sg[0]=0;
    
                int ans=0;
    
                    for(int j=1;j<=3;j++) {
    
                    ans^=mex(x[j]);//尼姆博弈
                    }
                  if(ans==0)
                    printf("Nacci
    ");
                  else
                    printf("Fibo
    ");
    
            }
            return 0;
        }
     
  • 相关阅读:
    NOI2004 郁闷的出纳员 [Splay]
    关押罪犯 [二分]
    SCOI2010 传送带 [三分/模拟退火]
    POI2007 MEG-Megalopolis [树状数组]
    食物链 [并查集]
    SDOI2011 染色 [树链剖分]
    国家集训队 数颜色 [莫队]
    JSOI2008 星球大战 [并查集]
    [NOI2002] 银河英雄传说 (带权并查集)
    种树 [堆]
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/4872763.html
Copyright © 2020-2023  润新知