首页 > 其他 > 详细

【BZOJ2275】[COCI2010] HRPA(斐波那契博弈)

时间:2020-05-18 10:41:13      阅读:46      评论:0      收藏:0      [点我收藏+]

点此看题面

大致题意:\(n\)个石头,每次取的石头数量不能超过另一个人前次取的石头数量的两倍,取到最后一个石头赢。问先手第一次至少取多少石头,才能保证必胜。

前言

稀奇古怪的博弈论题。。。

说实话我并不知道斐波那契博弈除了这道板子题以外还能干什么。。。

斐波那契博弈

对于这道题,有这样一个结论:对于一个斐波那契数,先手必须一次取完,否则必输。

考虑用归纳思想证明。

对于\(Fib_1=1\)\(Fib_2=2\)的情况,这个结论显然成立。

否则对于第\(i\)个斐波那契数\(Fib_i=Fib_{i-2}+Fib_{i-1}\),假设我们已经证明这一结论对于\(Fib_{i-2}\)\(Fib_{i-1}\)成立。

而斐波那契数满足性质\(2Fib_x\ge Fib_{i+1}\),所以如果先手不一次取完,且取的石头数\(\ge Fib_{i-2}\),显然后手可以一次取完。

因此先手不能一次取完\(Fib_{i-2}\)。而我们把\(Fib_{i-2}\)\(Fib_{i-1}\)分别看作两堆石头,则根据对\(Fib_{i-2}\)已经证明的这一结论,后手必然可以取到\(Fib_{i-2}\)这堆中的最后一个石头。

考虑后手最后一次取最多也只能是取\(\frac23\times Fib_{i-2}\)个石头(即先手一次取走\(\frac13\times Fib_{i-2}\)个石头),而\(\frac 43\times Fib_{i-2}\)显然是小于\(Fib_{i-1}\)的。

这也就意味着先手不能一次取完\(Fib_{i-1}\)这一堆,而根据对\(Fib_{i-1}\)已经证明的这一结论,后手可以取到\(Fib_{i-1}\)这一堆的最后一个石头,也就是\(Fib_i\)中的最后一个石头。

于是这个结论就得证了。

而我们考虑一个非斐波那契数,我们可以把它分解成若干个非连续的斐波那契数(因为连续的斐波那契数\(Fib_{i-2},Fib_{i-1}\)可以拼成\(Fib_i\))的和。

此时先手怎样才能赢呢?

由于斐波那契数的性质\(2Fib_x<Fib_{x+2}\),对于这些非连续的斐波那契数,一次取完较小的一堆后,另一个人无法一次取完较大的一堆。

所以,先手只要取走最小的斐波那契数,就能让自己成为后手,然后从小到大依次取完每一堆,就必胜了。

而具体代码实现是非常简单的。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define LL long long
using namespace std;
LL n,Fib[60];
int main()
{
	RI i;for(scanf("%lld",&n),Fib[1]=1,Fib[2]=2,i=3;(Fib[i]=Fib[i-2]+Fib[i-1])<n;++i);//求斐波那契数
	W(n^Fib[i]) n>Fib[i]&&(n-=Fib[i]),--i;return printf("%d",n),0;//斐波那契分解,答案是最小的斐波那契数
}

【BZOJ2275】[COCI2010] HRPA(斐波那契博弈)

原文:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2275.html

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