刚开始想用sg函数做,想了半天没一点思路啊。

原来这是一个新题型,斐波那契博弈

斐波那契博弈模型:
有一堆个数为 n 的石子,游戏双方轮流取石子,满足:
1. 先手不能在第一次把所有的石子取完;
2. 之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍)。
约定取走最后一个石子的人为赢家,求必败态。

 n = 2时输出second;     
 n = 3时也是输出second; 
 n = 4时,第一个人想获胜就必须先拿1个,这时剩余的石子数为3,此时无论第二个人如何取,第一个人都能赢,输出first; 
 n = 5时,first不可能获胜,因为他取2时,second直接取掉剩下的3个就会获胜,当他取1时,这样就变成了n为4的情形,所以输出的是second;   
 n = 6时,first只要去掉1个,就可以让局势变成n为5的情形,所以输出的是first;      
 n = 7时,first取掉2个,局势变成n为5的情形,故first赢,所以输出的是first;     
 n = 8时,当first取1的时候,局势变为7的情形,第二个人可赢,first取2的时候,局势变成n为6得到情形,也是第二个人赢,取3的时候,second直接取掉剩下的5个,所以n = 8时,输出的是second;    
 …………      
 从上面的分析可以看出,n为2、3、5、8时,这些都是输出second,即必败点,仔细的人会发现这些满足斐波那契数的规律,可以推断13也是一个必败点。     
 借助“Zeckendorf定理”(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和。n=12时,只要谁能使石子剩下8且此次取子没超过3就能获胜。因此可以把12看成8+4,把8看成一个站,等价与对4进行"气喘操作"。又如13,13=8+5,5本来就是必败态,得出13也是必败态。也就是说,只要是斐波那契数,都是必败点。
所以我们可以利用斐波那契数的公式:fib[i] = fib[i-1] + fib[i-2],只要n是斐波那契数就输出second
证明转自:http://blog.csdn.net/dgq8211/article/details/7602807

为了方便,我们将n记为f[i]。

1、当i=2时,先手只能取1颗,显然必败,结论成立。

2、假设当i<=k时,结论成立。

则当i=k+1时,f[i] = f[k]+f[k-1]。

则我们可以把这一堆石子看成两堆,简称k堆和k-1堆。

(一定可以看成两堆,因为假如先手第一次取的石子数大于或等于f[k-1],则后手可以直接取完f[k],因为f[k] < 2*f[k-1])

对于k-1堆,由假设可知,不论先手怎样取,后手总能取到最后一颗。下面我们分析一下后手最后取的石子数x的情况。

如果先手第一次取的石子数y>=f[k-1]/3,则这小堆所剩的石子数小于2y,即后手可以直接取完,此时x=f[k-1]-y,则x<=2/3*f[k-1]。

我们来比较一下2/3*f[k-1]与1/2*f[k]的大小。即4*f[k-1]与3*f[k]的大小,对两值作差后不难得出,后者大。

所以我们得到,x<1/2*f[k]。

即后手取完k-1堆后,先手不能一下取完k堆,所以游戏规则没有改变,则由假设可知,对于k堆,后手仍能取到最后一颗,所以后手必胜。

即i=k+1时,结论依然成立。

还有一点2^31 = 2 147 483 648,这个超过int范围了,所以用long long,fib到第46项即可

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const double g=10.0,eps=1e-;
const int N=+,maxn=,inf=; int f[N],sg[N],Hash[N];
void getsg(int n)
{
for(int i=;i<=n;i++)
{
memset(Hash,,sizeof Hash);
for(int j=;f[j]<=i;j++)
Hash[sg[i-f[j]]]=;
for(int j=;j<n;j++)
if(!Hash[j])
{
sg[i]=j;
break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
ll n;
ll fib[N];
fib[]=fib[]=;
for(int i=;i<=;i++)
fib[i]=fib[i-]+fib[i-];
// cout<<fib[46]<<endl;
while(cin>>n,n){
bool flag=;
for(int i=;i<=;i++)
if(n==fib[i])
{
flag=;
break;
}
if(flag)cout<<"Second win"<<endl;
else cout<<"First win"<<endl;
}
return ;
}

hdu2516斐波那契博弈的更多相关文章

  1. 20-取石子动态规则(hdu2516 斐波那契博弈)

    http://acm.hdu.edu.cn/showproblem.php?pid=2516 取石子游戏 Time Limit: 2000/1000 MS (Java/Others)    Memor ...

  2. 取石子游戏 HDU2516(斐波那契博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2516 题目: Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任 ...

  3. {HDU}{2516}{取石子游戏}{斐波那契博弈}

    题意:给定一堆石子,每个人最多取前一个人取石子数的2被,最少取一个,最后取石子的为赢家,求赢家. 思路:斐波那契博弈,这个题的证明过程太精彩了! 一个重要的定理:任何正整数都可以表示为若干个不连续的斐 ...

  4. HDU 2516 取石子游戏(斐波那契博弈)

    取石子游戏 Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  5. HDU 2516 取石子游戏 斐波纳契博弈

    斐波纳契博弈: 有一堆个数为n的石子,游戏双方轮流取石子,满足: 1)先手不能在第一次把所有的石子取完: 2)之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍) ...

  6. hdu 2516 取石子游戏 (斐波那契博弈)

    题意:1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍. 取完者胜,先取者负输出"Second win",先取者胜 ...

  7. BZOJ2275[Coci2010]HRPA——斐波那契博弈

    题目描述 N个石子,A和B轮流取,A先.每个人每次最少取一个,最多不超过上一个人的个数的2倍.取到最后一个石子的人胜出,如果A要有必胜策略,第一次他至少要取多少个. 输入 第一行给出数字N,N< ...

  8. 简单易懂的博弈论讲解(巴什博弈、尼姆博弈、威佐夫博弈、斐波那契博弈、SG定理)

    博弈论入门: 巴什博弈: 两个顶尖聪明的人在玩游戏,有一堆$n$个石子,每次每个人能取$[1,m]$个石子,不能拿的人输,请问先手与后手谁必败? 我们分类讨论一下这个问题: 当$n\le m$时,这时 ...

  9. 博弈论基础知识: 巴什博奕+斐波那契博弈+威佐夫博奕+尼姆博弈(及Staircase)(转)

    (一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.最后取光者得胜.若(m+1) | n,则先手必败,否则先手必胜.显然,如果n=m+1 ...

随机推荐

  1. jquery操作select标签change事件

    $('#update_supply_id').on('change',function(){//判断是否选取prompt属性,无返回值: if($(this).val()){ var selectTe ...

  2. asp.net 下载文件几种方式

    protected void Button1_Click(object sender, EventArgs e) { /* 微软为Response对象提供了一个新的方法TransmitFile来解决使 ...

  3. hdu5542 The Battle of Chibi【树状数组】【离散化】

    The Battle of Chibi Time Limit: 6000/4000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Othe ...

  4. codeforces#516 Div2---ABCD

    A---Make a triangle! http://codeforces.com/contest/1064/problem/A 题意: 给定三个整数表示三角形的边.每次给边长可以加一,问至少要加多 ...

  5. Golang学习 - builtin 包

    Go builtin包提供了go预先声明的函数.变量等的文档.这些函数变量等的实现其实并不是在builtin包里,只是为了方便文档组织. 这些内置的变量.函数.类型无需引入包即可使用. 默认提供的有: ...

  6. BaseLayout

    angularjs2 knockoutjs framework7 jquerymobile bootstrap html5 css [Activity(Label = "ActivityBa ...

  7. mysql数据库建模Navicat

    用Navicat制作ER图及与SQL互相转化 http://wangbaiyuan.cn/sql-and-use-navicat-to-make-er-diagram-and-interactive. ...

  8. mysql float 浮点型

    定点数类型 DEC等同于DECIMAL 浮点类型:FLOAT DOUBLE 作用:存储薪资.身高.体重.体质参数等 m,d 都是设置宽度 =============================== ...

  9. MySQL5.7多源复制

    MySQL5.7开始支持多源复制,也就是多主一从的复制架构: 使用多源复制的考虑: 1.灾备作用:将各个库汇总在一起,就算是其他库都挂了(整个机房都无法连接了),还有最后一个救命稻草: 2.备份:直接 ...

  10. MySQL中特有的函数If函数

    上面我们已经知道了case函数可以实现逻辑判断,可以是很复杂的逻辑判断,但是如果我们只想实现的是如果这个条件成立就返回A否则就返回B这样简单的逻辑如果用case的话,未免复杂了.我们可以使用if函数来 ...