Fibonacci again and again

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

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
 
 
 

取石子问题,一共有3堆石子,每次只能取斐波那契数个石子,先取完石子者胜利,问先手胜还是后手胜

 
求sg值,
 #include <bits/stdc++.h>
using namespace std; /*
s数组表示合法移动集合,从小到大排序。sNum合法移动个数
sg数组初始化为-1,对每个集合s仅需初始化1次
*/
const int MAXN = ;//s集合大小
const int MAXM = + ;//
int s[MAXN], sNum;
int sg[MAXM]; int dfsSg(int x)
{
if (sg[x] != -) {
return sg[x];
}
int i;
bool vis[MAXN];//sg值小于等于合法移动个数sNum memset(vis, false, sizeof(vis));
for (i = ; i < sNum && s[i] <= x; ++i) {
dfsSg(x - s[i]);
vis[sg[x - s[i]]] = true;
}
for (i = ; i <= sNum; ++i) {
if (!vis[i]) {
sg[x] = i;
break;
}
}
return sg[x];
} int main()
{
int i;
s[] = ;
s[] = ;
for (i = ; i < MAXN; ++i) {
s[i] = s[i - ] + s[i - ];
//printf("%d %d\n", i, s[i]);
}
sNum = ;
int m, n, p;
int sum;
memset(sg, -, sizeof(sg));
while (~scanf("%d%d%d", &m, &n, &p)) {
if (m == && n == && p == ) {
break;
}
dfsSg(m);
dfsSg(n);
dfsSg(p);
sum = sg[m] ^ sg[n] ^ sg[p];
if (sum != ) {
printf("Fibo\n");
} else {
printf("Nacci\n");
}
}
return ;
}
 #include <bits/stdc++.h>
using namespace std; /*
s数组表示合法移动集合,从小到大排序。sNum合法移动个数
sg值对每个集合s仅需求一次
*/
const int MAXN = ;//s集合大小
const int MAXM = + ;//
int s[MAXN], sNum;
int sg[MAXM];
bool exist[MAXN];//sg值小于等于合法移动个数sNum void getSg(int n)
{
int i, j;
sg[] = ;//必败态
for (i = ; i <= n; ++i) {
memset(exist, false, sizeof(exist));
for (j = ; j < sNum && s[j] <= i; ++j) {
exist[sg[i - s[j]]] = true;
}
for (j = ; j <= sNum; ++j) {
if (!exist[j]) {
sg[i] = j;
break;
}
}
}
} int main()
{
int i;
s[] = ;
s[] = ;
for (i = ; i < MAXN; ++i) {
s[i] = s[i - ] + s[i - ];
//printf("%d %d\n", i, s[i]);
}
sNum = ;
int m, n, p;
int sum;
getSg();
while (~scanf("%d%d%d", &m, &n, &p)) {
if (m == && n == && p == ) {
break;
}
sum = sg[m] ^ sg[n] ^ sg[p];
if (sum != ) {
printf("Fibo\n");
} else {
printf("Nacci\n");
}
}
return ;
}

hdu 1848 Fibonacci again and again(sg)的更多相关文章

  1. hdu 1848 Fibonacci again and again (SG)

    题意: 3堆石头,个数分别是m,n,p. 两个轮流走,每走一步可以选择任意一堆石子,然后取走f个.f只能是菲波那契中的数(即1,2,3,5,8.....) 取光所有石子的人胜. 判断先手胜还是后手胜. ...

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

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

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

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

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

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

  5. hdu 1848 Fibonacci again and again(简单sg)

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

  6. 题解报告:hdu 1848 Fibonacci again and again(尼姆博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1848 Problem Description 任何一个大学生对菲波那契数列(Fibonacci num ...

  7. 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)运算 ...

  8. 【HDU1848】Fibonacci again and again(博弈论)

    [HDU1848]Fibonacci again and again(博弈论) 题面 Hdu 你有三堆石子,每堆石子的个数是\(n,m,p\),你每次可以从一堆石子中取走斐波那契数列中一个元素等数量的 ...

  9. HDU 1024 Max Sum Plus Plus (动态规划)

    HDU 1024 Max Sum Plus Plus (动态规划) Description Now I think you have got an AC in Ignatius.L's "M ...

随机推荐

  1. 转载的shell命令73条

    1.检查远程端口是否对bash开放: echo >/dev/tcp/8.8.8.8/53 && echo "open" 2.让进程转入后台: Ctrl + z ...

  2. make编译四

    书写命令 每条规则中的命令和操作系统 Shell 的命令行是一致的. make 会按顺序一条一条的执行命令, 每条命令的开头必须以[Tab]键开头, 除非,命令是紧跟在依赖规则后面的分号后的.在命令行 ...

  3. centos7 安装python3.6

    •到python官网找到下载路径, 用wget下载 wget https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz •解压tgz包 tar ...

  4. 隐马尔可夫模型(hidden Markov model,HMM)

    定义: 隐马尔科夫模型是关于时序的概率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测而产生观测随机序列的过程. 隐马尔科夫模型由初始概率分布.状态转移概率分布 ...

  5. 【转载】Java中使用Jedis操作Redis

    1 package com.test; 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.Li ...

  6. Maven学习笔记—坐标和依赖

    Maven的坐标和依赖 1 Maven坐标 1.1 什么是Maven坐标 Maven坐标:世界上任何一组构件都可以使用Maven坐标来唯一标识,Maven坐标的元素包括groupId.artifact ...

  7. C# W3 调试

    如果在调试附加进程中 没W3进程的话, 在运行里输入 uac  设置为从不通知 即可:

  8. 虚拟化qemu-img的简单用法。

    qemu-img 命​令​行​工​具​是​ Xen 和​ KVM 用​来​格​式​化​各​种​文​件​系​统​的​,可​使​用​ qemu-img 格​式​化​虚​拟​客​户​端​映​像​.​附​加​ ...

  9. 算法题 19 二叉平衡树检查 牛客网 CC150

    算法题 19 二叉平衡树检查 牛客网 CC150 实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1. 给定指向树根结点的指针TreeNode* ro ...

  10. Linux基础系列:常用命令(1)

    1.开启Linux操作系统,要求以root用户登录GNOME图形界面,语言支持选择为汉语 2.使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 命令:ctrl+alt+F2 3.使用命 ...