CodeForces 520B Two Buttons

知识点:贪心、递推、反向思考

题目

Vasya has found a strange device. On the front panel of a device there are: a red button, a blue button and a display showing some positive integer. After clicking the red button, device multiplies the displayed number by two. After clicking the blue button, device subtracts one from the number on the display. If at some point the number stops being positive, the device breaks down. The display can show arbitrarily large numbers. Initially, the display shows number n.
Bob wants to get number m on the display. What minimum number of clicks he has to make in order to achieve this result?

输入

The first and the only line of the input contains two distinct integers n and m (1 ≤ n, m ≤ 104), separated by a space .

输出

Print a single number — the minimum number of times one needs to push the button required to get the number m out of number n.

样例

输入1

4 6

输出1

2

输入2

10 1

输出2

9

提示

In the first example you need to push the blue button once, and then push the red button once.
In the second example, doubling the number is unnecessary, so we need to push the blue button nine times.

题意

对一个数,每次选择两个操作:1、乘二 2、减一,最少几次操作可以得到目标数字。

思路

之前做过的题忘了怎么贪了。
因为只有减1能减少数值,且只能减1,无法越过目标数字,所以数字大于目标数字的时候只能使用减1。只有乘2能增加数值,但可以越过目标数字,所以数字小于目标数字的时候,为了使数字大于或等于目标数字,必须乘2,但不是只能乘2,通过减1再乘2也可以达到目的。
通过样例1可以发现:如果选择先乘2再减2,则需要3步;而先减1再乘2,则只需要2步。可证明一个数先乘2再减2相当于这个数先减1再乘2,即2*n-2=(n-1)*2,等式左边使用了3步,而等式右边只用了2步。而且因为数字是任意给的,所以3步可以化成2步,且与数字本身状态无关,表示需要应用贪心思想解题。
通过上述思路可知,若数字小于目标数字,必须乘2,当乘2后的数字与目标数字的距离大于1时,便可以贪心,多次迭代可得到乘2后与目标数字的距离为0或1,因为乘2后得到的数字一定是偶数,则当目标数字为偶数时,迭代后的距离为0,奇数为1。
也就是说能否贪心要看乘2后的状态,根据乘2后的状态推断乘2前需要减1几次。若最开始数字仍然小于乘2之前的数字,根据上述文字,乘2之前必须还有乘2操作。而乘2之前需要减1几次又可通过乘2之前的乘2操作贪心,减1几次可化为减1零次或一次。
循环直到乘2前的数字小于或等于最开始的数字。这个数字又只能由最开始的数字减1几次得到,最开始的数字之前没有任何乘2操作,故减1几次无法化成0次或1次。
实现思路见代码。

代码

//克服WA难,终得AC
#include"bits/stdc++.h"
#define ll long long
#define rep(i,a,b) for(ll i=a;i<b;i++)
#define reb(i,a,b) for(ll i=a;i<=b;i++)
#define rev(i,a,b) for(ll i=a-1;i>=b;i--)
#define red(i,a,b) for(ll i=a;i>=b;i--)
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;

int main() {
   
  ll s,e;//起始数字,目标数字
  cin>>s>>e;
  ll cnt=0;//迭代过程中的操作次数
  while(s<e) {
   //不要写成s<=e,否则当s==e时会继续执行操作,而s之前没有任何操作。
    if(e&1) {
   
    //e为奇数,由乘2后的偶数减1得到,要得到乘2后的偶数需要e加1
      e++;
      cnt++;
    }
    //得到乘2前的数字
    e>>=1;
    cnt++;
  }
  //无法贪心部分为(s-e)次
  cout<<cnt+s-e<<endl;

  return 0;
}
全部评论

相关推荐

04-12 21:52
南开大学 Java
鼠鼠有点摆,去年边学着没敢投简历,没实习。从1月到现在总共面了五次,四次字节的日常(HR打电话约面试才敢去的),然后一次腾讯的暑期,都是一面挂,其他则是没给面。暑期的岗,4.2才开始海投,前面想着等字节第四次一面后再投,结果挂,而且感觉投晚了。字节投了11个,9个简历挂,剩下2个没动静。阿里全都简历挂,剩下的在&quot;投递简历&quot;。腾讯给了一次面。然后其他大中厂、手机厂什么的都是做完测评or笔试就没下文,打开几个看也是终止流程,感觉剩下的也应该是简历挂了。感觉是简历的原因?项目部分,几次面试,感觉面试官主要就拷问过秒杀这一个点。自己说的时候会尝试把sse那条说成亮点,但除了腾讯面试官问过一下这整个点在业务方面对用户有什么用之类的问题外,其他最多只是问一下sse八股...感觉也许不是很让面试官感兴趣。这个短链接也是无人问津,就被问过一回雪花算法的设计。也许我该拿点评改改,然后再在网上找一个什么项目,凑两个,而不是用自己现在这两个项目?或者是点评改改放前面,然后原本第一个项目,把秒杀抽掉,剩下的想办法从网上火的RAG项目里移植点亮点,或者直接就用网上的RAG项目?感觉我主要还是偏向后端开发,但是感觉如果除开点评,再拿一个项目,想不到有什么自己能掌控且跟点评不重的。然后鼠鼠之前主要的问题是担心面试让打开项目演示,然后就一直花时间在用AI整第一个项目,第二个项目都没时间整,第四次面试之前还因为太害怕被认为不熟悉项目,跟AI一起把简历的说辞做了大幅度弱化,然后暑期都是拿弱化后的简历投的,感觉是不是看上去太没有吸引力就直接给简历挂了。(图1是弱化后的,图2是弱化前的,但之前3月初投了几家好像也是简历挂。)而且因为3月花了很多时间整在跟AI整代码,导致八股和算法都没怎么看,算法之前有跟灵神题单刷一些,还算入门,但是八股只看了一些基本的,可能面试的时候只答得上来60-70%,而且表述有些混乱,都是想到哪说到哪;前面几回面试基本上都有大板块的基础八股没答出来,比如RedisZ&nbsp;Set数据结构,MQ延时消息、可靠性保证,JVM内存分配的过程、GC&nbsp;roots,JUC锁,设计模式。现在有点不知道该怎么办。求大佬们给点简历修改建议或者面试准备建议,不胜感激!
何时能不做牛马:简历每个点之间的间距可以缩一下。几乎没遇到过要演示项目的情况,即使万一遇上了你也可以说部署在其他电脑上本地没代码。nku不应该简历挂吧?抓紧背背八股练练表达,不要放弃,五六月份找到也不晚(不然还得提前入职
应届生简历当中,HR最关...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务