首先我们很容易得到状态转移方程dp[i]=(dp[k*i],dp[i+l])+1{1<=l<=t}
根据这个转移方程我们需要快速求得min{dp[i+l]}(1<=l<=t)
我们知道这种形式的就是单调队列优化dp的标准形式
维护一个dp[i]从队尾到队头递增的队列
每次算好dp[i]的时候把队尾中dp值小于等于dp[i]的都出队(队列里面的都是下标比i大的,值又没i优,是无用的)
然后dp[i]=min(dp[q[head]],dp[k*i])+1
#include<set>
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define MS(a,b) memset(a,b,sizeof(a))
const int N=1e6+10;
int dp[N],q[N];
int main()
{
int T,x,k,t;
scanf("%d",&T);
while(T--){
int head=0,tail=0;
scanf("%d%d%d",&x,&k,&t);
MS(dp,0);
dp[x]=0;
q[tail++]=x;
for(int i=x-1;i>=1;i--)
{
dp[i]=dp[q[head]]+1;
if(1ll*i*k<=x)dp[i]=min(dp[i],dp[k*i]+1);//开始这里写错了没注意,感谢 航行的帆船给我提出
if(q[head]-t>=i&&head<tail)head++;
while(tail>head&&dp[i]<=dp[q[tail-1]])tail--;
q[tail++]=i;
}
printf("%d\n",dp[1]);
}
return 0;
}