SG函数

关键:

找出子情况中,求出子情况未出现的最小正整数就是母情况的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;
}
原文地址:https://www.cnblogs.com/chinacwj/p/7045409.html