HDU 1848 Fibonacci again and again SG函数详解!

Fibonacci again and again

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6854    Accepted Submission(s): 2848


Problem 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、  最先取光所有石子的人为胜者;

假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。
 

Input
输入数据包含多个测试用例,每个测试用例占一行,包含3个整数m,n,p(1<=m,n,p<=1000)。
m=n=p=0则表示输入结束。
 

Output
如果先手的人能赢,请输出“Fibo”,否则请输出“Nacci”,每个实例的输出占一行。
 

Sample Input
  
  
1 1 1 1 4 1 0 0 0
 

Sample Output
  
  
Fibo Nacci
 
思路:

SG函数的基本应用,什么是SG函数??这个我不能多说,资料很多,何况我也是刚刚接触,万一误导大家。

这样来看,如果对于单一堆的话。他的取法会怎么样?对于总数为  fibonacci 数列中的数,先手肯定必胜,例如总数为  1   2   3  5   8,那么对于其他情况那?这里我们首先来考虑一个  4  。对于  4

 无论先手怎样取,都会失败,也就是说4是一个必败点!假定此处的  SG 为  0 。然后再来考虑一个特殊点   0  ,此时无数可取,当然也是必败。次数 SG 也设为 0  

那么  对于必胜点来说  SG =  0  ,必败点  SG=0  ,相信这个为什么不用我多说吧,如果不知道,还是去看一下有关SG函数的知识。

贴出传送门:    传送门已就绪~~

对于 1 来说,他的取法只有  1

也就是说    1  -   1   =  0  ,  和  0  等价的只有  0  

1  的全部后继节点   构成一个集合  {  0   }

对这个集合进行运算 mex { 0 } =  1  。也就是说 SG 1= 1.

对于 2 来说,他的取法有  1  和  2

可以得到的剩余个数   1   0   1  和  1 等价,0  和  0 等价  ,

mex{ 0 1 } =2 ;   SG2=2

3  也是同样,我们来看 4几个特殊的。

对于 4 来说 取法有 1 2 3

可以得到的剩余个数有  3,2,1.   分别和   32 1 等价

mes1,2,3=0;   SG4=0 ,我们上面已经知道4 是必败点。

对于 5 取法有  1 2 3 5

可以得到剩余的个数   4,3,2,0. 通过上面我们知道  SG4=0,也就是说  剩余  4个 和剩余0个没有区别,都是必败点。所以   他们分别等价于   0   3   2   0

mex{0,2,3}=1;   SG(5)=1;  也就是说   5  和  1  是等价的,这个可以理解吗?不理解的话,就请思考几遍。

再来看一个   

剩余个数             6                       7                         8

可取个数            1   2  3   5       1  2   3   5           1  2  3  5  8

剩余个数            5   4  3   1       6   5    4   2         7  6   5   3  0

等价于               1   0    3   1      2    1   0   2         3   2   1   3   0

mex运算               2                      3                       4

等价于可以看做  其 SG  值。

那么SG值代表什么呢?

假设  x SG 值为  k

那么 意义就是:x 的后继节点 出 sg 值可以为 0,1,2......k-1,甚至是 k+1,但是不可以保持k不变。因为每次操作都是要改变状态的!

而另外定义的运算mex是用来干什么的那??

我的理解是这样的!!咳咳~~

nimu博弈里面, p  n  的转化关系还记得吗?

p 的后继节点至少有一个  n   n  的所有后继节点都是  p

也就是说,SG  = 0 时,下一个 总是 SG = 0

                  SG = 0 时,后继节点至少有一个  SG =  0

mex运算就是用来实现这个的功能的,求出最小的SG可能。那么他可以达到的后继都比他小,对吗?

我不知道我是否说的清楚。

然后SG不是还有一个性质吗?

SG _total   =   SG (1)  ^ SG (2) ^ ......SG (n).

具体为什么?

还有为什么 SG = 0 为必败,SG = 0 为必胜?

结合着拓扑图,我试着来证明一下。(证明不出来的话大家就别看了。)

先来看一下  对于一堆小石块的游戏。


贴出传送门:     传送门已就绪~~













对于 1  2  显然是  必胜点,对于  3  他只能通向必胜点,也就是说他的下一步操作会将必胜点送给对手。

对于 4 呢?可以选择把必胜给对方,也可以选择把必败给对方。当然最优抉择是把必败给对方。

我们完全可以用 p  n  来表示整个图。SG != 0 为 p 否则 为  n 。

这样的话。因为  p  n 的转化关系。(尼姆博弈里面说的很详细了,包括证明都很厉害)


再来看下一个问题:

为什么对于多组博弈

SG _total   =   SG (1)  ^ SG (2) ^ ......SG (n).

再回到尼姆博弈中来......

还记得当时证明为什么在尼姆博弈中 sum ^  后为0 就输,不为 0  就胜吗?

其实这个证明和那个完全相同

贴出传送门:不会的同学去看一下:

传送门

感觉写的很乱的。希望对看到的同学有帮助。

感想:

这个东西想了一天了,累死,今天终于有点懂了。博弈就先搞到这里吧,先去学点别的压压惊。。


AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
int sg[1005];
int fibo[1005];
int mex[1005];
int main()
{
    int a,b,c,pp,i,j;
    fibo[0]=fibo[1]=1;
    fibo[2]=2;
    for(i=3;i<1004;i++)
    {
        fibo[i]=fibo[i-1]+fibo[i-2];
    }
    memset(sg,0,sizeof(sg));
    sg[1]=1;//这里是必胜点设为  p
    sg[2]=2;
    sg[3]=3;
    for(i=4;i<1002;i++)
    {
        memset(mex,0,sizeof(mex));
        for(j=0;fibo[j]<=i;j++)
            mex[sg[i-fibo[j]]]=1;
        for(j=0;;j++)
        {
            if(mex[j]==0)
            {
                sg[i]=j;
                break;
            }
        }
    }
    while(cin>>a>>b>>c)
    {
        pp=0;
        int num=0;
        int sum=0;
        if(a+b+c==0) break;
        sum=sg[a]^sg[b]^sg[c];
        //cout<<sum<<endl;
        if(!sum)
        {
            cout<<"Nacci"<<endl;
        }
        else
            cout<<"Fibo"<<endl;
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值