HZOJ 511. 最少操作次数

题目描述

​ 给出两个整数 a,b,每次操作可以把 a 变成 a+1 或 a∗k 。求把 a 变成 b 至少需要几步操作。


输入

​ 第一行三个数 a,b,k。(0≤a,b,k≤1018)

输出

​ 输出最少操作次数。


样例输入
2 10 2
样例输出
3

数据规模与约定

​ 时间限制:1 s

​ 内存限制:256 M

​ 100% 的数据保证 0≤a,b,k≤1e18

这道题第一眼的思路很容易想到:直接暴力广搜,但显然,数据量这么大,会超时。这里主要介绍贪心解法。

首先我们要了解一个基础知识,就是关于进制。对于一个n进制数而言,用它再乘上n,相当于在其末尾加上了一个0,理解的话,类比十进制就好,当然这也很好想通。那么我们可以这样想,对于两个数a,b,我们把它想象成题目里给的k进制,举个例子:a:12345,b:123456780,以上分别是两个数字的k进制形式。那么我们可以想了,怎么样才能最快地从a到b呢?我这里直接给出答案:a先乘上k,变成123450,然后再加6,也就是123456,继续重复上述操作:1234560,1234567,12345670,12345678,123456780,如此,我们便在六步之内完成操作。其他方案一定会比这样慢,可以自行验证。

当然,这道题的难点主要在于如何去转化这个思路成代码,不过上面的思路没有相关经验也很难想到就是了。先来总结一下我们上述的思路:例如我们现在有1432 和 12,都是k进制数,我们的转变是这样的:14,140,143,1430,1432,其实我们可以总结出:当当前的数字完全等于我们所要的数字的某个前缀的时候,我们将之乘上k是最优方法。当然也可能出现已经大于前缀的情况,例如1432和24, 这里就只能将24加到132然后再去乘k了。否则的话我们可以想一想,24乘两次k就会大于1432,乘一次k的话,剩下的就只能不断地去加了。其他情况也全都比这个要次数多。

接下来介绍我们的贪心方程:

当a<=b:ans+=1+b%k,b/=k;当a>b:ans+=b-a,并结束循环。

解释一下。第一个方程的意思实际上是:前面那个1代表乘一次,后面那个b%k代表咱们每次乘之前所需要加上的值,举例就是,1430*5+2=1432  14*5+3=143,以上就是两次1+b%k操作。然后最后的b-a,对应的就是12+2=14的操作。所以这其实和上面我们一开始说的操作顺序是相反的。

当然,上述式子有些难以理解的话,也可以直接硬做,也就是都转换成k进制再按我们之前的方法做。这样比较好理解,也比较容易想到,就是写起来略显麻烦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值