【hdu 5945 】 【dp+单调队列优化】Fxx and game【求数x最少经过多少次变换能变为1,(1)如果x%k==0,那么可以x=x/k。(2)x=x-i,(1<=i<=t)】

本文介绍了一个数字游戏的问题背景及解决思路,使用动态规划方法求解如何将初始数字通过特定操作步骤减少到1的最少步数,并提供了基于单调队列优化的高效实现方案。

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

传送门:http://acm.split.hdu.edu.cn/showproblem.php?pid=5945

描述:

青年理论计算机科学家Fxx给的学生设计了一款数字游戏。

一开始你将会得到一个数\:XX,每次游戏将给定两个参数\:k,tk,t, 任意时刻你可以对你的数执行下面两个步骤之一:

1.\:X = X - i(1 <= i <= t)1.X=Xi(1<=i<=t)2.\:2.\:X\:X\:k\:k的倍数,X = X / kX=X/k。

现在Fxx想要你告诉他最少的运行步骤,使\:X\:X变成\:11

思路:

设dp[i]为i变为1的最小步骤,

当i%k==0时 dp[i]=min(dp[i / k],dp[j])+1{i-t<=j<=i-1}

否则     dp[i]=min(dp[j])+1{i-t<=j<=i-1}

min(dp[j])相当于维护区间[i-t,i-1]最小值。如果纯暴力,复杂度会有 O(N2) ;在这个题目里面, 线段树还是会超时,复杂度为 O(Xlog2(X)) 。如果考虑用单调队列来优化,复杂度为 O(N) 。 


代码:

#include <bits/stdc++.h>
using  namespace  std;
#define mst(ss,b) memset(ss,b,sizeof(ss));
#define rep(i,k,n) for(int i=k;i<=n;i++)

const int inf=0x3f3f3f3f;
const int N=1e6+10;

int deq[N];//单调队列优化,维护下标
int dp[N], x, k, t;

void solve(){
  int l, r;
  l = r = 1; dp[1] = 0; deq[1] = 1; 
  rep(i, 2, x){
    while(l <= r && deq[l] < i - t)l++; //单调队列中最多只能有t个元素
    if(l <= r)dp[i] = dp[deq[l]] + 1;
    if(i % k == 0)dp[i] = min(dp[i], dp[i / k] + 1);
    while(l <= r && dp[deq[r]] >= dp[i])r--; //保持单调性
    deq[++r] = i;
  }
}

int  main(){
  int T;
  scanf("%d", &T);
  while(T--){
    scanf("%d%d%d", &x, &k, &t);
    mst(dp, inf);
    solve();
    printf("%d\n", dp[x]);
  }
  return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值