SG函數
結論:遊戲和的SG函數等於各個遊戲SG函數的Nim和
應用條件:當進行遊戲有多種選取方式,可以打sg表或者用dfs得到
例題:
有三堆石子,每堆石子的數量爲n,m,k.每次每人可以拿去的石子數量爲斐波那契的項的數量,
1、 這是一個二人遊戲;
2、 一共有3堆石子,數量分別是m, n, p個;
3、 兩人輪流走;
4、 每走一步可以選擇任意一堆石子,然後取走f個;
5、 f只能是菲波那契數列中的元素(即每次只能取1,2,3,5,8…等數量);
6、 最先取光所有石子的人爲勝者;
//f[N]:可改變當前狀態的方式,N爲方式的種類,f[N]要在getSG之前先預處理
//SG[]:0~n的SG函數值
//S[]:爲x後繼狀態的集合
#include <stdio.h>
#include <string.h>
#define MAXN 1000 + 10
#define N 20
int f[N],SG[MAXN],S[MAXN];
void getSG(int n){
int i,j;
memset(SG,0,sizeof(SG));
for(i = 1; i <= n; i++){
memset(S,0,sizeof(S));
for(j = 0; f[j] <= i && j <= N; j++)
S[SG[i-f[j]]] = 1;
for(j = 0;;j++) if(!S[j]){
SG[i] = j;
break;
}
}
}
int main(){
int n,m,k;
f[0] = f[1] = 1;
for(int i = 2; i <= 16; i++)
f[i] = f[i-1] + f[i-2];
getSG(1000);
while(scanf("%d%d%d",&m,&n,&k),m||n||k){
if(SG[n]^SG[m]^SG[k]) printf("Fibo\n");
else printf("Nacci\n");
}
return 0;
}