题目链接: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. C++ 文件操作(简易的学籍管理系统)

    这是一个简易的学籍管理系统,大一时居然三个人写了一千多行......年少无知啊!欢迎摘果实! 1 #include <iostream> #include <fstream> ...

  2. (办公)MojoExecutionException

    MojoExecutionException : mavan打包错误. 通过以下命令解决:mvn clean install (新改的内容生效)

  3. MySQL 基础知识梳理学习(五)----详解MySQL两次写的设计及实现

    一 . 两次写提出的背景或要解决的问题 两次写(InnoDB Double Write)是Innodb中很独特的一个功能点.因为Innodb中的日志是逻辑的,所谓逻辑就是比如插入一条记录时,它可能会在 ...

  4. httpservlet里单纯分页

    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletExcep ...

  5. 如何设置Oracle数据库客户端字符集以及系统中的NLS_LANG环境变量

    概述: 本地化是系统或软件运行的语言和文化环境.设置NLS_LANG环境参数是规定Oracle数据库软件本地化行为最简单的方式. NLS_LANG参数不但指定了客户端应用程序和Oracle数据库所使用 ...

  6. 阿里巴巴JAVA开发手册

    Java编程规约 (一)命名风格      1. [强制] 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束.           反例: _name / __name / $O ...

  7. python字符串replace失效问题

    python字符串replace替换无效 背景 今天想把一个列表中符合条件的元素中 替换部分字符串, 发现怎么替换,改元素还是没有改变,本以为是内存引用的问题后来发现并不然. 经查阅解决 在Pytho ...

  8. MAX

    Max的用法1(Min类似) Matlab中max函数在矩阵中求函数大小的实例如下: C = max(A)返回一个数组各不同维中的最大元素.如果A是一个向量,max(A)返回A中的最大元素.如果A是一 ...

  9. Emit动态代理.NetCore迁移之旅

    [前言] 前面我们介绍了Aop 从静态代理到动态代理:https://www.cnblogs.com/7tiny/p/9657451.html 我们在.NetFramework平台下使用微软提供的Em ...

  10. js把变量转换成json数据

    var a="";var MessageList=JSON.stringify(a);