您的位置:首页 > 大数据 > 人工智能

HDU 1848 Fibonacci again and again(博弈_SG函数)

2015-11-12 21:51 751 查看
【题目链接】

http://acm.hdu.edu.cn/showproblem.php?pid=1848

【解题报告】

一堆石子的问题可以直接维护sg函数。求出G
的sg值(我的理解是,把n-1,n-2,n-3,n-5…这些状态通过sg值转换为n-1,n-2,n-3,n-4…这些状态,即不连续的拿取状态映射为连续的拿取状态,这样就可以把这道题目转化为像HDU1849这样的典型nim问题来求解)

三堆石子那么SG( n,m,p )=SG
^SG[m]^SG[p]

(和解决nim问题是类似的)

SG=0那么是个P状态(必败)

SG=1那么是个N状态(必胜)

求SG值的时间复杂度为O(n^2).在本题小数据范围内可解。有时间研究下存不存在O(nlogn)的解法。

【参考资料】

《SG函数资料》–冰刃逆袭丿

http://blog.sina.com.cn/s/blog_83d1d5c70100y9yd.html

【参考代码】

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

const int maxn=1000;
int sg[maxn+50],fib[20];
int cnt;

void init()
{
memset(fib,0,sizeof(fib));
memset(sg,0,sizeof(sg));
fib[0]=1;fib[1]=1;
cnt=1;
while(fib[cnt]<=1000)
{
fib[++cnt]=fib[cnt-1]+fib[cnt-2];
}

for( int i=1; i<=maxn; i++ )
{
int tag[1000];
memset(tag,0,sizeof(tag));
for( int j=1; j<=cnt; j++ )
{
if(fib[j]>i)break;
tag[ sg[i-fib[j]] ]=1;  //i可以达到i-fib[j]这个状态,即可以到达对应的sg值
}
int j=0;
while(tag[j])j++;
sg[i]=j;
}
}

int main()
{
init();
int m,n,p;
while(~scanf("%d%d%d",&m,&n,&p) && (m+n+p) )
{
int state=0;
state=state^sg[m]^sg
^sg[p];
if(state)printf("Fibo\n");
else printf("Nacci\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: