• HDU 1848 Fibonacci again and again


    Fibonacci again and again

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

    遇到的第一道需要使用sg函数的题目。

    这里转一个推导。反正自己一下子想不明白。

    首先确定这样的博弈游戏属不属于组合游戏的范畴:
    1、有且仅有两个玩家 2、游戏双方轮流操作 3、游戏操作状态是个有限的集合(比如:取石子游戏,石子是有限的,棋盘中的棋盘大小的有限的) 4、游戏必须在有限次内结束 5、当一方无法操作时,游戏结束。

    例子推导

    例如:取石子问题,有1堆n个的石子,每次只能取{1,3,4}个石子,先取完石子者胜利,那么各个数的SG值为多少?

    sg[0]=0,f[]={1,3,4},

    x=1时,可以取走1-f{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1;

    x=2时,可以取走2-f{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0;

    x=3时,可以取走3-f{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1;

    x=4时,可以取走4-f{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;

    x=5时,可以取走5-f{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;

    以此类推.....

       x         0  1  2  3  4  5  6  7  8....

    sg[x]      0  1  0  1  2  3  2  0  1....

    计算从1-n范围内的SG值。

    f(存储可以走的步数,f[0]表示可以有多少种走法)

    f[]需要从小到大排序

    1.可选步数为1~m的连续整数,直接取模即可,SG(x) = x % (m+1);

    2.可选步数为任意步,SG(x) = x;

    3.可选步数为一系列不连续的数,用getSG()计算

    那么这个题的标程

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<map>
     7 #include<vector>
     8 #define mem(a,b) memset(a,b,sizeof(a))
     9 #define ll long long
    10 #define inf 1000000000
    11 #define maxn 1005
    12 #define maxm 100005
    13 #define eps 1e-10
    14 #define for0(i,maxn) for(int i=1;i<=(maxn);++i)
    15 #define for1(i,maxn) for(int i=1;i<=(maxn);++i)
    16 #define for2(i,x,y) for(int i=(x);i<=(y);++i)
    17 #define for3(i,x,y) for(int i=(x);i>=(y);--i)
    18 #define mod 1000000007
    19 using namespace std;
    20 inline int read()
    21 {
    22     int x=0,f=1;char ch=getchar();
    23     while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    24     while(ch>='0'&&ch<='9') {x=10*x+ch-'0';ch=getchar();}
    25     return x*f;
    26 }
    27 int f[maxn],sg[maxn],hash1[maxn];
    28 void getSG(int n)
    29 {
    30     mem(sg,0);
    31     for(int i=1;i<=n;++i)
    32     {
    33         mem(hash1,0);
    34         for(int j=1;f[j]<=i;j++)
    35            hash1[sg[i-f[j]]]=1;
    36         for(int j=0;j<=n;++j)
    37         {
    38             if(hash1[j]==0) {
    39                 sg[i]=j;break;
    40             }
    41         }
    42     }
    43 }
    44 int main()
    45 {
    46     int m,n,t;
    47     f[0]=f[1]=1;
    48     for(int i=2;i<=16;++i) 
    49     f[i]=f[i-1]+f[i-2];
    50     getSG(1000);
    51     while(~scanf("%d%d%d",&n,&m,&t))
    52     {
    53         if(m==0&&n==0&&t==0) break;
    54         if((sg[n]^sg[m]^sg[t])==0) 
    55         puts("Nacci");
    56         else puts("Fibo");
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    【交换】
    【数字对】
    【改造二叉树】
    【Begin】
    100以内所有质数的输出
    位运算符、|和||、&和&&的区别
    linux中vim编辑器三种模式及常用命令的使用
    静态代码块、构造代码块和构造函数的执行顺序
    字符乱码出现的原因及解决办法
    Springcloud-微服务
  • 原文地址:https://www.cnblogs.com/TYH-TYH/p/9418901.html
Copyright © 2020-2023  润新知