首页 > 其他 > 详细

nyoj-358 取石子(五)(斐波那契博弈)

时间:2014-04-21 07:06:02      阅读:567      评论:0      收藏:0      [点我收藏+]

取石子(五)

时间限制:1000 ms  |  内存限制:65535 KB
难度:4
描述
himdd最近很想玩游戏,于是他找到acmj和他一起玩,游戏是这样的:有一堆石子,两个人轮流从其中取走一定的石子,取走最后所有石子的人为赢家,不过得遵循如下规则:
1.第一次取不能取完,至少取1颗.

2.从第二次开始,每个人取的石子数至少为1,至多为对手刚取的石子数的两倍。

himdd事先想知道自己会不会赢,你能帮帮他吗?(每次himdd先手)

输入
有多组测试数据,每组有一个整数n(2<=n<2^64);
输出
himdd会赢输出Yes,否则输出No;
样例输入
2
5
6
样例输出
No
No
Yes


思路:

      结论:当n为fibonacci数时,先手必败(n >= 2);

      证明:

      参考资料:http://blog.csdn.net/dgq8211/article/details/7602807

      以下为个人思路:

      根据“Zeckendorf定理”(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和(优先选取最大的)。

      比如 n = 14 时, n = 8 + 5 + 1;而先手要赢的条件是,先手必须要先取完最小的一堆,再取完次小的一堆,以此类推,并保证每堆的最后一个是自己取到的而且不能取超!听起来有点绕,举个例子:

      先看必胜态,n不是fibonacci数的时候,令n = 9 =5 + 3 + 1:

            a、先手先取最小的一堆,1个,保证了最后一个是自己取得;

            b、此时后手开始取次小的一堆(3个石子),上面说过,要想赢的话,要保证这一堆的第3个必须是自己取得;此时后手有 1、2两种取法,但此处无论后手怎么取,都能

           保证这一堆的最后一个(第3个)是自己取得;

            c、此时后手开始取最后一堆(5个石子),b步先手可能取得是1或2,因此此步后手可能有1、2、3、4四种取法,易知后手取3或4的话,自己立马就能取到最后一个,就

            赢了,而取1或2时,同上(读者自己来),仍能保证取到最后一个(此堆第5个,全局最后一个),必赢!

      再说必败态,若n是fibonacci数时,为方便观察,令n=5:

      fib[i] = fib[i-1] + fib[i - 2]; 即 5 = 3 + 2;实际上与上面相反,无论自己怎么取,后手都能保证自己取到最小一堆的最后一个,因此后手必胜!


代码:

#include <stdio.h>
#define N 100

long long fib[N];

void Fib()
{
	fib[0] = 0;
	fib[1] = 1;
	for(int i = 2; i < N; i ++){
		fib[i] = fib[i - 1] + fib[i - 2];
	}
}

int main()
{
	Fib();

	long long n;
	while(scanf("%lld", &n) != EOF){
		bool is_fib = 0;
		for(int i = 2; i < 100; i ++){
			if(fib[i] == n){
				is_fib = 1;
				break;
			}
		}

		if(is_fib)
			printf("No\n");
		else
			printf("Yes\n");
	}

	return 0;
}







nyoj-358 取石子(五)(斐波那契博弈),布布扣,bubuko.com

nyoj-358 取石子(五)(斐波那契博弈)

原文:http://blog.csdn.net/tbl_123/article/details/24033245

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!