HDU 1848 Fibonacci again and again (斐波那契博弈SG函数)
Posted Ritchie丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1848 Fibonacci again and again (斐波那契博弈SG函数)相关的知识,希望对你有一定的参考价值。
Time Limit: 1000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64u |
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、 最先取光所有石子的人为胜者;
假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。
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则表示输入结束。
m=n=p=0则表示输入结束。
Output
如果先手的人能赢,请输出“Fibo”,否则请输出“Nacci”,每个实例的输出占一行。
Sample Input
1 1 1
1 4 1
0 0 0
Sample Output
Fibo
Nacci
题意如题。
题解:求sg值即可,因为i的后继都是小于i的,即i的后继的sg值已知,所以可以不搜索,给出两种AC代码。
利用dfs求sg函数:
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N = 1005; const int M = 25; int fib[25]; int SG[N]; int mex(int x) { bool vis[M]; memset(vis,0,sizeof(vis)); for(int i=0;i<M;i++) { int t = x - fib[i]; if(t < 0) break; if(SG[t] == -1) SG[t] = mex(t); vis[SG[t]] = 1; } for(int i=0;;i++) if(!vis[i]) return i; } void Init() { fib[0] = 1; fib[1] = 2; for(int i=2;i<M;i++) fib[i] = fib[i-1] + fib[i-2]; memset(SG,-1,sizeof(SG)); for(int i=0;i<N;i++) SG[i] = mex(i); } int main() { Init(); int a,b,c; while(~scanf("%d%d%d",&a,&b,&c)) { if(a == 0 && b == 0 && c == 0) break; int ans = 0; ans ^= SG[a]; ans ^= SG[b]; ans ^= SG[c]; if(ans) puts("Fibo"); else puts("Nacci"); } return 0; }
非深搜:
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N = 1005; const int M = 25; int fib[25]; int SG[N]; void get() { bool vis[M]; for(int i=0;i<N;i++) //sg数组 { memset(vis,0,sizeof(vis)); for(int j=0;j<M&&fib[j]<=i;j++) //要用的s数组 注意这里有等号 { vis[SG[i-fib[j]]]=1; } for(int x=0;x<N;x++) if(!vis[x]) { SG[i]=x; break; } } } void Init() { fib[0] = 1; fib[1] = 2; for(int i=2;i<M;i++) fib[i] = fib[i-1] + fib[i-2]; memset(SG,0,sizeof(SG)); //这里定义成 -1和0都可以 get(); } int main() { Init(); int a,b,c; while(~scanf("%d%d%d",&a,&b,&c)) { if(a == 0 && b == 0 && c == 0) break; int ans = 0; ans ^= SG[a]; ans ^= SG[b]; ans ^= SG[c]; if(ans) puts("Fibo"); else puts("Nacci"); } return 0; }
以上是关于HDU 1848 Fibonacci again and again (斐波那契博弈SG函数)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 1848 Fibonacci again and again
HDU1848 Fibonacci again and again(SG函数)
hdu 1848 Fibonacci again and again(SG函数)
HDU 1848(sg博弈) Fibonacci again and again