关键:
找出子情况中,求出子情况未出现的最小正整数就是母情况的sg值,一般SG[0] = 0;(即当前人遇到0的情况时,他就已经输了,必败点),然后从这个点一直推出母问题的情况,
多堆,就用异或(^=)
代码实现(hdu 1848)
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <string.h>
#define ll long long
using namespace std;
int sg[1005];
bool cmp(int a,int b)
{
return sg[a]<sg[b];
}
vector<int> nxt[1005];
int m,n,p;
int f[101];
int solve(int a)
{
memset(sg,0,sizeof(sg));
for(int i=1;i<=a;i++) nxt[i].clear();
for(int i=1;i<=a;i++)
{
//cout<<i<<endl;
for(int j=1;;j++)
{
int x=i-f[j];
//cout<<f[j]<<endl;
if(x<0) break;
else
{
//cout<<x<<endl;
nxt[i].push_back(x);
}
}
}
for(int i=1;i<=a;i++)
{
sort(nxt[i].begin(),nxt[i].end(),cmp);
int k=0;
for(int j=0;j<nxt[i].size();j++)
{
//cout<<nxt[i][j]<<" "<<sg[nxt[i][j]]<<endl;
if(i==12)
{
//cout<<nxt[i][j]<<" "<<sg[nxt[i][j]]<<endl;
//cout<<sg[nxt[i][j]]<<endl;
}
if(sg[nxt[i][j]]==k)
{
k++;
sg[i]++;
}
}
}
return sg[a];
}
int main()
{
f[1]=1;
f[2]=2;
for(int i=3;i<=25;i++)
{
f[i]=f[i-1]+f[i-2];
//cout<<f[i]<<endl;
}
while(~scanf("%d %d %d",&m,&n,&p))
{
if(m==0&&n==0&&p==0) break;
//solve(m);
//cout<<solve(m)<<" "<<solve(n)<<" "<<solve(p)<<endl;
int ans=solve(m)^solve(n)^solve(p);
printf(ans?"Fibo
":"Nacci
");
}
return 0;
}