Fibonacci again and again

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4248    Accepted Submission(s): 1768

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
 
Source
 

用SG函数做的第一道题。
对于SG函数,还是有些不太懂,
可是,我看以下说的,就有些明确了:

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算。表示最小的不属于这个集合的非负整数

比如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每一个顶点的Sprague-Grundy函数g例如以下:g(x)=mex{ g(y) | y是x的后继 },这里的g(x)即sg[x]

比如:取石子问题,有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()计算

上述是自jumping_frog博文的建立SG模板时的解释,稍后我也会做个SG函数的模板。

这道题,有了上述方法,就简单了。
首先建立f数组,就是Fibonacci数列。
然后预处理求1000以内的SG数组,通过模板:
// 获得SG数组函数模板。t代表f数组的个数,n代表要求的sg数组上限
// f数组就是能取的个数(对于此题就是Fibonacci数列
// 有时,对于t已知就不须要单独传參
void get_sg(int t,int n)
{
int i,j;
memset(sg,0,sizeof(sg));
for(i=1;i<=n;i++)
{
memset(mex,0,sizeof(mex));
// 对于属于g(x)后继的数置1
for( j=1 ;j<=t && fib[j]<=i ;j++ )
mex[sg[i-fib[j]]]=1;
// 找到最小不属于该集合的数
for( j=0 ; j<=n ; j++ )
if(!mex[j])
break;
sg[i] = j;
}
}

SG的题。非常多都能够看成是多个Nim博弈。

然后就能够分析神秘态,非神秘态来确定答案了。


然后就是此题完整代码:
/************************************************
*************************************************
* Author:Tree *
*From :http://blog.csdn.net/lttree *
* Title : Fibonacci again and again *
*Source: hdu 1848 *
* Hint : SG *
*************************************************
*************************************************/
#include <stdio.h>
#include <string.h>
int fib[21]; //fib保存Fibonacci数列
int sg[1001];//sg[]来保存SG值
bool mex[1001];//mex{}
// 构建SG数组,函数各步骤意义详见上面模板
void get_sg(int n)
{
int i,j;
memset(sg,0,sizeof(sg));
for(i=1;i<=n;i++)
{
memset(mex,0,sizeof(mex));
for( j=1 ;fib[j]<=i ;j++ )
mex[sg[i-fib[j]]]=1; for( j=0 ; j<=n ; j++ )
if(!mex[j])
break;
sg[i] = j;
}
}
int main()
{
int i,m,n,p;
// 构建Fibonacci数列
fib[0]=1,fib[1]=1;
for(i=2;i<21;++i) fib[i]=fib[i-1]+fib[i-2];
// 预处理获得sg数组
get_sg(1000);
while( scanf("%d%d%d",&m,&n,&p) && m+n+p )
{
if( (sg[m]^sg[n]^sg[p])==0 ) printf("Nacci\n");
else printf("Fibo\n");
}
return 0;
}

ACM-SG函数之Fibonacci again and again——hdu1848的更多相关文章

  1. hdu-------(1848)Fibonacci again and again(sg函数版的尼姆博弈)

    Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  2. HDU 1848 Fibonacci again and again(SG函数)

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  3. HDU1848 Fibonacci again and again SG函数

    Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  4. HDU 1848 Fibonacci again and again (斐波那契博弈SG函数)

    Fibonacci again and again Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  5. HDU1848 Fibonacci again and again(SG 函数)

    任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的: F(1)=1; F(2)=2; F(n)=F(n-1)+F(n-2)(n>=3); 所以,1, ...

  6. HDU 1848 Fibonacci again and again【SG函数】

    对于Nim博弈,任何奇异局势(a,b,c)都有a^b^c=0. 延伸: 任何奇异局势(a1, a2,… an)都满足 a1^a2^…^an=0 首先定义mex(minimal excludant)运算 ...

  7. hdu 1848 Fibonacci again and again (初写SG函数,详解)

    思路: SG函数的应用,可取的值为不连续的固定值,可用GetSG求出SG,然后三堆数异或. SG函数相关注释见代码: 相关详细说明请结合前一篇博客: #include<stdio.h> # ...

  8. HDU 1848 Fibonacci again and again(SG函数入门)题解

    思路:SG打表 参考:SG函数和SG定理[详解] 代码: #include<queue> #include<cstring> #include<set> #incl ...

  9. 【博弈论】【SG函数】hdu1848 Fibonacci again and again

    某个状态的SG函数被定义为 除该状态能一步转移到的状态的SG值以外的最小非负整数. 有如下性质:从SG值为x的状态出发,可以转移到SG值为0,1,...,x-1的状态. 不论SG值增加与否,我们都可以 ...

随机推荐

  1. md5 c# unicode 互换(原创)

    php 代码 $input='中国'; $result= md5($input); $temp=iconv("UTF-8", "UTF16LE", $input ...

  2. HTML中href、src区别

    href是Hypertext Reference的缩写,表示超文本引用.用来建立当前元素和文档之间的链接.常用的有:link.a.例如: <link href="reset.css&q ...

  3. SwiftUI 官方教程(六)

    6. 在列表和详情之间设置导航 虽然列表已经能显示了,但是我们还不能通过点击单个地标来查看地标详情页面.SwiftUI教程 把 list 嵌入一个 NavigationView 中,并把每个 row  ...

  4. POJ 1654 乱搞题?

    题意: 从一个点出发,8个方向,给出每一步的方向,求出走过的路径形成的多边形的面积. 思路: 先普及一下向量叉乘.. (摘自度娘) 也就是x1y2-x2y1. 那这不就好说了嘛. 一个经过原点的闭合多 ...

  5. java三大版本解析

    JAVA三大版本代表着JAVA技术的三个应用领域:JAVASE.JAVAME.JAVAEE. JAVA以前很长一段时间被称为JAVA2,所以现在很多人习惯称为J2SE.J2ME.J2EE,它们表示的含 ...

  6. Linux下实现视频读取

    V4L(video4linux是一些视频系统,视频软件.音频软件的基础,经常时候在需要采集图像的场合,如视频监控,webcam,可视电话,经常使用在embedded linux中是linux嵌入式开发 ...

  7. 小程序-wx:for

    wx:for (列表渲染) index默认数组下标item默认数组当前项的变量名 数组是对象的形式,单纯写{{item}},结果是[object object]的形式,必须加对象名,并且对象名基本设置 ...

  8. 使用Caffe预测遇到的问题

    1. 在使用网络预测图像时, prediction = net.predict( [input_image] ) 出现: net.image_dims[0] 不是整数情况, (2).甚至以为np.ze ...

  9. LINQ(Language Integrated Query)

    LINQ http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html LINQ是.NET Framework 3.5的新特性,其全称 ...

  10. 关于pc端 app端pdf,word xls等文件预览的功能

    第一种用H5标签<iframe>标签实现 返回的文件类型,文件流,文件流返回必须在设置 contentType对应的Mime Type, 返回文件的物理位置. 已经实测可以支持的文件类型 ...