题目链接:点击查看
题目大意:给出 n 个石子,两人轮流取石子,取到最后一个石子的人获胜,规定:
- 第一次取石子不能全部取完
- 后续取石子的数量必须不超过前一次的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;
}