1.题目链接。一开始想直接搜索过了,但是发现似乎不得行。然后dp可做,因为上一状态向下一状态的转移最多只有t+1个
dp[i]=min(dp[i-1],dp[i-2]....dp[i-t])+1当k|x时,dp[i]=min(dp[i],dp[i/k]+1).所以这个状态数有限,单调队列维护一下前i-t个最值即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int dp[maxn];//dp[i]表示i走到1的最小的步数
int Q[maxn];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
memset(Q, 0, sizeof(Q));
memset(dp, 0, sizeof(dp));
int X, k, t;
scanf("%d%d%d", &X, &k, &t);
if (t == 0)
{
int ans = 0;
while (X != 1)
{
X /= k;
ans++;
}
cout << ans << endl;
continue;
}
if (k == 1)
{
int ans = 0;
ans = X / t;
if (X % t>1)ans++;
cout << ans << endl;
continue;
}
dp[1] = 0;
int head =1,tail = 1;
Q[1] = 1;
for (int i = 2; i <= X; i++)
{
while (head <= tail && Q[head] < i - t)
head++;
dp[i] = dp[Q[head]] + 1;
if (i % k == 0)
dp[i] = min(dp[i], dp[i / k]+1);
while ((head <= tail) && dp[i] <= dp[Q[tail]])
tail--;
Q[++tail] = i;
}
cout << dp[X] << endl;
}
}