题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1848

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
 
解题思路:
以下介绍摘自博客:https://www.cnblogs.com/ECJTUACM-873284962/p/6921829.html

SG函数:

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

对于任意状态 x , 定义 SG(x) = mex(S),其中 S 是 x 后继状态的SG函数值的集合。如 x 有三个后继状态分别为 SG(a),SG(b),SG(c),那么SG(x) = mex{SG(a),SG(b),SG(c)}。 这样 集合S 的终态必然是空集,所以SG函数的终态为 SG(x) = 0,当且仅当 x 为必败点P时。

【实例】取石子问题

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

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

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

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

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

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

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

以此类推.....

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

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

由上述实例我们就可以得到SG函数值求解步骤,那么计算1~n的SG函数值步骤如下:

1、使用 数组f 将 可改变当前状态 的方式记录下来。

2、然后我们使用 另一个数组 将当前状态x 的后继状态标记。

3、最后模拟mex运算,也就是我们在标记值中 搜索 未被标记值 的最小值,将其赋值给SG(x)。

4、我们不断的重复 2 - 3 的步骤,就完成了 计算1~n 的函数值。

本题只要求出每堆石子的sg值,然后异或即可,如果非0,先手赢,否则后手赢

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e3+;
int f[maxn],sg[maxn],s[maxn];
//f[]表示改变当前状态的方式
//sg[]表示每个状态的sg值
//s[]标记后继节点转态的集合
int m,n,p;
void getSG(int n){
memset(sg,,sizeof(sg));
//sg[0]=0,所以循环从1开始
for(int i=;i<=n;i++){
memset(s,,sizeof(s));
for(int j=;j<=n&&f[j]<=i;j++)
s[sg[i-f[j]]]=;//当前节点可以转到的下一状态标记
for(int j=;j<=n;j++){ //查询当前后继状态SG值中最小的非零值
if(!s[j]){
sg[i]=j;
break;
}
}
}
}
int main()
{
f[]=; f[]=;
for(int i=;;i++){
f[i]=f[i-]+f[i-];
if(f[i]>=)break;
}
getSG());
while(cin>>m>>n>>p){
if(m+n+p==)break;
if(sg[m]^sg[n]^sg[p])
puts("Fibo");
else puts("Nacci");
}
return ;
}

hdu 1848 简单SG函数的更多相关文章

  1. S-Nim HDU 1536 博弈 sg函数

    S-Nim HDU 1536 博弈 sg函数 题意 首先输入K,表示一个集合的大小,之后输入集合,表示对于这对石子只能去这个集合中的元素的个数,之后输入 一个m表示接下来对于这个集合要进行m次询问,之 ...

  2. HDU 1847 Good Luck in CET-4 Everybody!(找规律,或者简单SG函数)

    Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  3. hdu 1809 求SG函数

    A New Tetris Game(2) Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  4. hdu 1536 S-Nim (简单sg函数)

    题意:首先输入K 表示一个集合的大小  之后输入集合 表示对于这对石子只能去这个集合中的元素的个数 之后输入 一个m 表示接下来对于这个集合要进行m次询问 之后m行 每行输入一个n 表示有n个堆  每 ...

  5. HDU 5742 Chess SG函数博弈

    Chess Problem Description   Alice and Bob are playing a special chess game on an n × 20 chessboard. ...

  6. Alice and Bob HDU - 4111 (SG函数)

    Alice and Bob are very smart guys and they like to play all kinds of games in their spare time. The ...

  7. HDU 1848(sg博弈) Fibonacci again and again

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

  8. HDU 1536 求解SG函数

    #include<stdio.h> #include<string.h> #include<algorithm> #include<set> using ...

  9. SG函数和SG定理【详解】

    在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念:        P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败.        N点:必胜点 ...

随机推荐

  1. 腾讯云服务器配置node环境

    1:更新现有包 sudo apt-get update 2:安装依赖 sudo apt-get install vim openssl build-essential libssl-dev wget ...

  2. java新知识系列 六

    sleep和wait的区别有: Servlet方法的使用 方法重写的规则,以及两同两小一大原则: DispatcherServlet的解析 依赖注入DU和控制反转Ioc AOP和OOP的区别 Spri ...

  3. mysql免安装版初次使用

    在自己电脑上安装一个mysql数据库并启动,碰到一些问题,总结一下 1.下载免安装版mysql数据库,百度下载了了5.7.25版本 2.在bin文件夹下找到my-defaults.ini文件,我这没有 ...

  4. linux Page cache和buffer cache正解

    Page cache和buffer cache一直以来是两个比较容易混淆的概念,在网上也有很多人在争辩和猜想这两个cache到底有什么区别,讨论到最后也一直没有一个统一和正确的结论,在我工作的这一段时 ...

  5. 一天一个Linux命令--find

    文件查找:(以find为主)  which:查找命令字所在的位置  locate:模糊匹配(只要包含关键字的文件都查找出来)         不是实时的,基于数据库查找, updatedb升级loca ...

  6. GMM算法的matlab程序

    GMM算法的matlab程序 在“GMM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...

  7. 登陆验证AuthorizeAttribute

    自定义验证,验证失败后:Response.Redirect.

  8. python之面相对象程序设计

    一 面向对象的程序设计的由来 面向对象设计的由来见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 面向对象的程序设计:路飞学院版 ...

  9. 文本分类实战(六)—— RCNN模型

    1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 te ...

  10. HTML5仿手机微信聊天界面

    HTML5仿手机微信聊天界面 这篇文章主要为大家详细介绍了HTML5仿手机微信聊天界面的关键代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下     给大家带来的是HTML5仿手机微信聊天界面, ...