【HDU 5945】Fxx and game

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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值