Skip to content

喵~ 主人好呀!今天我们来分析一道超级可爱的题目:一只小蚱蜢在数轴上跳来跳去,我们要帮它规划路线,是不是很有趣呢?嘻嘻,就让本猫娘来带你轻松解决它吧!

A. Grasshopper on a Line (小蚱蜢跳跳乐)


题目大意

有一只小蚱蜢,它一开始在数轴上的原点 0。它想要跳到目标点 x 去。

小蚱蜢每次跳跃有一些小小的规则:

  1. 它可以向左或者向右跳。
  2. 跳跃的距离必须是一个整数。
  3. 最重要的一点:跳跃的距离不能是整数 k 的倍数。

我们的任务是,找出让小蚱蜢从 0 跳到 x 所需的最少的跳跃次数,并且给出一种具体的跳跃方案。如果有很多种方案,随便给出一种就可以啦,喵~


题解方法

这道题其实非常简单,只需要稍微动动小脑筋,进行一下分类讨论就好啦,就像猫咪思考是先伸左爪还是右爪一样!(ฅ'ω'ฅ)

我们可以把问题分成两种情况来考虑:

情况一:目标点 x 本身就不是 k 的倍数

如果 x 除以 k 的余数不为 0(也就是 x % k != 0),那事情就变得超级简单了!

小蚱蜢可以直接从 0 一步跳到 x。这一跳的距离就是 x,而 x 又不是 k 的倍数,完全符合规则!一步到达目的地,这肯定是不能再少的最少步数了。所以,答案就是跳 1 次,跳的距离是 x

情况二:目标点 xk 的倍数

如果 x 正好是 k 的倍数(也就是 x % k == 0),那小蚱蜢就不能一步跳 x 这么远了,因为这违反了“跳跃距离不能是 k 的倍数”的规则。

既然一步不行,那最少也得两步了,对吧?我们来试试看能不能用两步搞定。

我们需要找到两个数 ab,让它们满足:

  1. a + b = x
  2. a 不是 k 的倍数
  3. b 不是 k 的倍数

怎么找这样的一对 ab 最方便呢?嘿嘿,我们可以直接构造一个解出来!最简单的构造方法就是把 x 拆成 1x - 1

我们来检查一下这个方案可不可行:

  • 对于 1:题目中给定了 k >= 2,所以 1 肯定不是 k 的倍数。耶!
  • 对于 x - 1:我们已经知道 xk 的倍数,那么 x 可以写成 x = m * k(其中 m 是某个整数)。那么 x - 1 就是 m * k - 1。这个数除以 k 的话,会得到 m-1(或者说余 k-1),总之肯定不是整数倍!所以 x - 1 也绝对不是 k 的倍数。耶!

看吧,1x - 1 都满足条件!所以,当 xk 的倍数时,我们总能让小蚱蜢先跳 x - 1,再跳 1,用两步完美到达终点 x。因为一步是不可能的,所以两步就是最少的步数啦!


题解

下面就是这份思路的C++代码实现啦,是不是超级清晰明了呢,喵~

cpp
#include <iostream>

// 处理单个测试用例的函数
void solve() {
    int x, k;
    std::cin >> x >> k;

    // 情况一:x 不是 k 的倍数
    // 我们可以一步从 0 跳到 x,这是最少的步数
    if (x % k != 0) {
        std::cout << 1 << "\n"; // 只需要 1 步
        std::cout << x << "\n"; // 跳的距离是 x
    } 
    // 情况二:x 是 k 的倍数
    // 我们不能一步跳到 x,所以至少需要两步
    // 我们可以把它拆成两步:1 和 x - 1
    // 因为 k >= 2,所以 1 肯定不是 k 的倍数
    // 因为 x 是 k 的倍数,所以 x-1 肯定不是 k 的倍数
    // 这个两步方案总是可行的,并且是步数最少的
    else {
        std::cout << 2 << "\n"; // 需要 2 步
        std::cout << x - 1 << " " << 1 << "\n"; // 分别跳 x-1 和 1
    }
}

int main() {
    // 加上这两行可以让输入输出快一点,是竞赛中的好习惯哦~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t; // 测试用例的数量
    std::cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

知识点介绍

这道题虽然简单,但也包含了一些非常基础和重要的编程思想哦!

  1. 模运算 (Modulo Operation)

    • % 这个符号就是取模运算符。a % k 的结果是 a 除以 k 的余数。
    • 它是判断一个数是否为另一个数倍数的关键工具。如果 a % k == 0,就说明 ak 的倍数。这是本题解法的核心,喵!
  2. 分类讨论 (Case Analysis)

    • 根据 x % k 的结果是否为 0,我们将问题拆分成了两种更简单、更容易处理的情况。
    • 这种思想在解决各种问题时都非常有用,它可以帮助我们理清思路,避免遗漏各种可能性。
  3. 构造法 (Constructive Approach)

    • 在处理 xk 的倍数时,我们没有去“搜索”一个可行的解,而是直接“构造”了一个解,也就是 {x-1, 1}
    • 当题目要求你输出 "any valid solution"(任意一个可行解)时,构造法通常是最直接、最简单的策略。与其大海捞针,不如自己动手创造一个嘛!

好啦,这次的解题报告就到这里结束啦!希望主人能够喜欢。下次再遇到有趣的题目,再来找我玩吧,喵呜~ ( ´ ▽ ` )ノ

Released under the MIT License.