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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章