top1编程
← 返回题目
题解

【入门】恐龙园买玩具?

1 条题解

  • 0
    @ 2026-8-1 10:21:04

    解题思路

    题目里有 4 个条件,先看清楚

    小明要买两种恐龙玩具:

    • 霸王龙:每只 x 元
    • 三角龙:每只 y 元

    他一共带了 n 元,买玩具要满足这 4 个条件:

    1. 两种都要买:霸王龙至少 1 只,三角龙也至少 1 只;
    2. 霸王龙数量 >= 三角龙数量:霸王龙不能买得比三角龙少;
    3. 总数 >= 5:两种恐龙加起来至少 5 只,才够分给 5 位朋友;
    4. 不能有钱剩下:花的钱要刚好等于 n 元。

    把所有满足条件的购买方案都输出出来。

    核心思路:枚举霸王龙的数量 a

    我们设霸王龙的数量是 a,三角龙的数量是 b。

    小明一共带了 n 元,买了 a 只霸王龙(每只 x 元)之后,剩下的钱是:

    n - a * x
    

    如果剩下的钱能刚好买整数只三角龙,也就是 能被 y 整除,那么:

    b = (n - a * x) / y
    

    这样第 4 个条件(不剩钱)就自动满足了——因为剩下的钱全部拿去买三角龙了。

    所以我们只要 从小到大枚举 a(a 从 1 开始,且 a*x 不能超过总钱数 n),用公式算出 b,再检查剩下的 3 个条件:

    • b >= 1:三角龙也要买;
    • a >= b:霸王龙数量不少于三角龙数量;
    • a + b >= 5:总数够分给 5 位朋友。

    全都满足,就输出 a 和 b。

    用样例演示一遍(n=100,x=10,y=5)

    • a = 1:1*10=10,剩 90,90/5=18,b=18。但 a>=b?1>=18 不成立,跳过。
    • a = 2:2*10=20,剩 80,80/5=16,b=16。2>=16 不成立,跳过。
    • …… a 太小的时候,三角龙会买得比霸王龙多,都不满足。
    • a = 7:7*10=70,剩 30,30/5=6,b=6。7>=6 成立,7+6=13>=5 成立,输出 7 6
    • a = 8:8*10=80,剩 20,20/5=4,b=4。8>=4 成立,8+4=12>=5 成立,输出 8 4
    • a = 9:9*10=90,剩 10,10/5=2,b=2。9>=2 成立,9+2=11>=5 成立,输出 9 2
    • a = 10:10*10=100,剩 0,0/5=0,b=0。b>=1 不成立,跳过。

    所以样例输出的三行就是:

    7 6
    8 4
    9 2
    

    正好和题目要求一模一样!因为 a 是从小到大枚举的:先输出的方案霸王龙少,后输出的方案霸王龙多,正好满足题目要求的"霸王龙数量从少到多",顺序天然正确,不用再排序。

    再试一组数据(n=60,x=10,y=5)

    • a = 4:410=40,剩 20,20/5=4,b=4。4>=4 成立,4+4=8>=5 成立,输出 4 4(410+4*5=60 刚好不剩钱)
    • a = 5:5*10=50,剩 10,10/5=2,b=2。5>=2 成立,5+2=7>=5 成立,输出 5 2
    • a = 6:6*10=60,剩 0,b=0,b>=1 不成立,跳过。

    输出就是 4 4 和 5 2,用同样的方法核验:每一行都刚好花光 60 元。

    小结

    这种"枚举一种数量,用公式算出另一种数量,再逐个检查条件"的做法,叫做 枚举 + 判断。枚举 a 的时候就保证了"不剩钱"和"输出顺序",后面只需要判断 3 个条件,非常简单,也不容易出错。

    参考代码

    // 包含输入输出需要用到的头文件
    #include <iostream>
    using namespace std;
    
    int main() {
        // n 表示一共带的钱,x 表示一只霸王龙的价钱,y 表示一只三角龙的价钱
        int n, x, y;
        cin >> n >> x >> y;
    
        // 枚举霸王龙的数量 a
        // a 从 1 开始(霸王龙至少要买 1 只),并且 a*x 不能超过总钱数 n
        for (int a = 1; a * x <= n; a++) {
            // 买完 a 只霸王龙后剩下的钱
            int rest = n - a * x;
    
            // 剩下的钱必须能被三角龙的单价 y 整除,才能做到不剩钱
            if (rest % y != 0) {
                continue;
            }
    
            // 三角龙的数量 b
            int b = rest / y;
    
            // 条件1:三角龙也要买(b >= 1)
            // 条件2:霸王龙数量不少于三角龙数量(a >= b)
            // 条件3:总数够分给 5 位朋友(a + b >= 5)
            if (b >= 1 && a >= b && a + b >= 5) {
                // 先输出霸王龙数量 a,再输出三角龙数量 b,中间用空格隔开
                cout << a << " " << b << endl;
            }
        }
    
        return 0;
    }
    

    复杂度分析

    • 时间复杂度:O(n/x)。我们只用了一层 for 循环,枚举 a 从 1 到 n/x,循环次数大约是 n/x 次。题目里 n<=999,规模很小,就算 x=1 最多也就循环几百次,运行非常快。
    • 空间复杂度:O(1)。我们只用了 n、x、y、a、b、rest 这几个 int 变量,没有使用数组等额外空间。
    • 1