POJ - 3922 A simple stone game(K倍博弈-斐波那契博弈进阶)

题目链接:点击查看

题目大意:给出 n 个石子,两人轮流取石子,取到最后一个石子的人获胜,规定:

  1. 第一次取石子不能全部取完
  2. 后续取石子的数量必须不超过前一次的K倍

题目分析:大佬博客:https://blog.csdn.net/ta201314/article/details/44892055

上面的博客已经分析+证明的很清楚了,其他网上绝大部分的博客都是复制粘贴的,证明也是草草两句,让人看得匪夷所思,看过这个博客之后就豁然开朗了,这里就贴一下代码了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
       
typedef long long LL;
      
typedef unsigned long long ull;
       
const int inf=0x3f3f3f3f;
  
const int N=1e6+100;

int a[N];
 
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int w;
	cin>>w;
	int kase=0;
	a[0]=1;
	while(w--)
	{
		int n,k;
		scanf("%d%d",&n,&k);
		int i=1,j=0;
		while(a[i]<=n)
		{
			while(1LL*a[j]*k<a[i])
				j++;
			a[i+1]=a[i]+a[j];
			i++;
		}
		i--;//回溯到小于等于 n 的最大项 
		printf("Case %d: ",++kase);
		if(a[i]==n)
			puts("lose");
		else
		{
			while(n!=a[i])//找到可分解的最小项
			{
				n-=a[i];
				while(n<a[i])
					i--;
			}
			printf("%d\n",n);
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	

    return 0;
}
发布了691 篇原创文章 · 获赞 27 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104750643