Description
有一堆石子有n颗,双方轮流取石子。
先手第一次可以拿至少一个但是不能拿完
接下来每次取的石子至少为1个,至多为上一次拿的两倍
问先手是否有必胜策略
Solution
观(da)察(biao)发现先手必败当且仅当n为斐波那契数?!!!
考虑归纳证明:
设n是斐波那契数,n=a+b,a和b为n的前两个斐波那契数
设先手拿的石子数量为x,显然x<a,因为b<2*a
那么根据归纳,后手肯定可以取到第a颗石子(a为先手必败)
剩下的就是一个状态为b的子游戏,也是先手必败
但是唯一的问题就是后手取完a之后,先手是否能够一步将b取完
考虑后手要取到a一次最多取多少个,设为y
那么也就是x>=a/3,y<=2a/3
那么下一步先手最多能取4a/3颗石子,和b做比较显然后者大
也就是说先手一定不能一次取完b,所以先手必败
如果n不是斐波那契数,根据齐肯多夫定理n可以被分解成若干个不相邻的斐波那契数之和,设为Fib[a[1]]…Fib[a[k]],且Fib[a[i]]>2*Fib[a[i+1]]
那么先手只需要取完Fib[a[k]],后手一次取不完Fib[a[k-1]],所以变成了一个子游戏,根据上面的分析先手一定能够取到最后一颗
所以先手必胜
HDU2516取石子游戏
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int n,f[46];
map<int,int> fib;
int main() {
f[0]=f[1]=1;fib[1]=1;
fo(i,2,45) {
f[i]=f[i-1]+f[i-2];
fib[f[i]]=1;
}
while(scanf("%d",&n)) {
if (!n) break;
if (fib[n]) puts("Second win");
else puts("First win");
}
return 0;
}

879

被折叠的 条评论
为什么被折叠?



