题解:学而思编程 增长或翻倍

【题目来源】

学而思编程:增长或翻倍

【题目描述】

给定正整数 \(s\)\(t\),保证 \(s \le t\),我们希望利用增长翻倍的操作,让 \(s\) 变成 \(t\)

增长操作可以让数字加一,即 \(x\rightarrow x+1\)

翻倍操作可以让数字翻倍,即 \(x\rightarrow 2\times x\)

请问最少需要用多少步操作才能将 \(s\) 变成 \(t\)

【输入】

一行两个正整数,分别表示 \(s\)\(t\)

【输出】

一行一个整数,表示最少操作步数。

【输入样例】

1 4

【输出样例】

2

【核心思想】

  1. 问题分析:给定起始值 \(s\) 和目标值 \(t\)\(s \le t\)),通过增长\(x \rightarrow x+1\))和翻倍\(x \rightarrow 2x\))两种操作,求将 \(s\) 变为 \(t\) 的最少操作步数。这是一个逆向贪心问题,关键在于从 \(t\) 反向推导到 \(s\) 时,每一步选择最优的反向操作。

  2. 算法选择

    • 逆向思维:不从 \(s\) 正向枚举所有操作路径,而是从 \(t\) 反向操作回 \(s\),大幅降低搜索空间
    • 贪心策略:在反向过程中,优先选择除以 2(对应正向的翻倍),当且仅当 \(t\) 为偶数且 \(t/2 \ge s\) 时执行;否则执行减 1(对应正向的增长)。这种策略保证每一步都尽可能"大步前进"
  3. 关键步骤

    • 初始化:读取 \(s\)(起始值)、\(t\)(目标值),初始化步数计数器 \(step = 0\)
    • 逆向循环(当 \(t \neq s\) 时继续):
      • 判断能否除以 2:若 \(t \bmod 2 = 0\)\(t/2 \ge s\),则执行 \(t \leftarrow t/2\)\(step \leftarrow step + 1\)
        • 选择理由:翻倍是增长效率最高的操作,反向时除以 2 能最大幅度缩小 \(t\)\(s\) 的差距
        • 约束条件 \(t/2 \ge s\):确保除以 2 后不会"越过" \(s\),避免后续需要额外操作补回
      • 否则执行减 1\(t \leftarrow t - 1\)\(step \leftarrow step + 1\)
        • 选择理由:当 \(t\) 为奇数或 \(t/2 < s\) 时,除以 2 会导致结果小于 \(s\),不如逐步减 1 精确逼近
    • 终止条件:当 \(t = s\) 时,输出 \(step\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(\log t)\),每次除以 2 操作使 \(t\) 指数级减小,减 1 操作最坏情况下连续执行但受限于奇数间隔
    • 空间复杂度:\(O(1)\),仅使用常数个变量
  5. 逆向贪心的核心思想

    • 操作可逆性:增长(\(+1\))的逆操作是减 1,翻倍(\(\times 2\))的逆操作是除以 2,逆向过程与正向过程一一对应
    • 贪心最优性:从 \(t\) 反向时,优先选择"大步"(除以 2)总是优于或等于"小步"(减 1)的累积效果,因为 \(\times 2\) 是指数增长,其逆操作是指数缩减
    • 边界保护:条件 \(t/2 \ge s\) 防止贪心过度,确保每一步反向操作都在有效范围内
    • 与正向 BFS/DP 的对比:正向从 \(s\) 出发需要枚举两种分支,时间复杂度随步数指数爆炸;逆向从 \(t\) 出发每一步决策唯一, greedy 即可得到全局最优
    • 适用于操作可逆、且存在"高效操作"与"低效操作"之分的最短步数问题

【算法标签】

数学

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int s, t, step;  // s: 起点, t: 终点, step: 步数
int main()
{
    cin >> s >> t;  // 输入起点和终点
    while (s != t)  // 当起点不等于终点时循环
    {
        if (t % 2 == 0 && t / 2 >= s)  // 如果t是偶数且t/2≥s
        {
            t /= 2;  // 反向操作:除以2
        }
        else
        {
            t--;  // 反向操作:减1
        }
        step++;  // 步数加1
    }
    cout << step;  // 输出最小步数
    return 0;
}

【运行结果】

1 4
2
posted @ 2026-07-05 16:01  团爸讲算法  阅读(8)  评论(0)    收藏  举报