K倍动态减法(hdu 2486)

本文探讨了一种两人轮流从一堆石子中取石子的游戏策略。先手玩家第一次不能取完所有石子但至少取一个,之后每轮取石子的数量不能超过对手上一轮取石子数量的K倍。文章通过构造数列的方法确定了先手是否有必胜策略,并给出了先手第一步至少要取多少个石子才能确保胜利。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:两人取一堆石子,石子有n个。 先手第一次不能全部取完但是至少取一个。之后每人取的个数不能超过另一个人上一次取的数的K倍。拿到最后一颗石子的赢。先手是否有必胜策略?若有,先手第一步最少取几个?
先来篇论文
再来篇博客(感觉人家讲的比我好,我就不献丑了)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+10;
int a[maxn],b[maxn];
int main()
{
    int ncase,Z=0;
    scanf("%d",&ncase);
    while(ncase--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        a[0]=b[0]=1;
        int i=0,j=0;
        while(n>a[i])//构造数列
        {
            i++;
            a[i]=b[i-1]+1;
            while(a[j+1]*k<a[i]) j++;
            if(a[j]*k<a[i]) b[i]=b[j]+a[i];
            else b[i]=a[i];
        }
        printf("Case %d: ",++Z);
        if(a[i]==n)
        {
            printf("lose\n");
            continue;
        }
        int ans;
        while(n)//减法求先手第一步
        {
            if(n>=a[i]) n-=a[i],ans=a[i];
            i--;
        }
        printf("%d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值