专栏文章
题解:P6487 [COCI 2010/2011 #4] HRPA
P6487题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minvhj6t
- 此快照首次捕获于
- 2025/12/02 09:01 3 个月前
- 此快照最后确认于
- 2025/12/02 09:01 3 个月前
这道题目是一个经典的博弈论问题,需要找出Mirko第一次至少取多少石子才能保证获胜。
问题分析
游戏规则简述:
- 两位玩家轮流取石子,Mirko先行
- Mirko第一次可以取任意数量的石子
- 之后每次取石子的数量必须在1到上一次取的数量的2倍之间
- 取走最后一颗石子的玩家获胜
我们需要找到Mirko第一次最少取多少石子才能确保胜利,假设双方都采用最优策略。
解题思路
这个问题的关键是发现它与斐波那契数列的紧密联系。通过分析可以发现,当石子数量是某个斐波那契数时,后行者有必胜策略;而当石子数量不是斐波那契数时,先行者有必胜策略。
解法的核心思想是:
- 生成所有不超过的斐波那契数
- 从最大的斐波那契数开始,不断从中减去,直到变为0
- 最后一次减去的斐波那契数就是答案
代码
CPP#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
cin >> n;
// 生成斐波那契数列,直到超过n
vector<long long> fib;
fib.push_back(1);
fib.push_back(1);
while(fib.back() < n)
{
int size = fib.size();
fib.push_back(fib[size-1] + fib[size-2]);
}
long long ans = n;
// 不断减去最大可能的斐波那契数
while(n)
{
for(int i = fib.size() - 1; i >= 0; i--)
{
if (fib[i] <= n)
{
ans = fib[i];
n -= fib[i];
break;
}
}
if (n == 0) break;
// 移除数列中大于当前n的数
while(fib.back() > n)
{
fib.pop_back();
}
}
cout << ans << endl;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...