Skip to content

喵~ 主人,你好呀!我是你的专属猫娘助手,今天也要元气满满地和你一起解决编程难题哦!这次我们要看的题目是 Codeforces 上的 B. Pashmak and Flowers,一个关于花朵和美丽值的可爱问题,听起来就很有趣呢,我们开始吧!

题目大意喵

Pashmak 想从他的花园里摘两朵花送给心上人 Parmida。花园里有 n 朵花,第 i 朵花的美丽值为 b_i

Parmida 是个有点特别的女孩子,她不一定想要最漂亮的两朵花。她想要的是这样的一对花:它们的美丽值之差是所有可能组合中最大的!

我们的任务就是帮助 Pashmak 计算两件事:

  1. 最大的美丽值差是多少。
  2. 有多少种不同的摘花组合可以达到这个最大差值。

比如说,如果花的美丽值是 [3, 1, 2, 3, 1],最大的差值就是 3 - 1 = 2。而能达到这个差值的组合有 4 种(第一个3和第一个1,第一个3和第二个1,第二个3和第一个1,第二个3和第二个1)。

解题思路喵!

这道题其实就像小猫玩毛线球一样,理清线头就好啦!我们可以分两步走,喵~

第一步:找到最大差值

想让两朵花的美丽值之差最大,该怎么做呢?喵呜~ 当然是选一朵最最最美丽的花和一朵最最最不起眼的花啦!也就是说,最大差值就是所有花中最大的美丽值 (max_b) 减去最小的美丽值 (min_b)。

所以,我们只需要遍历一遍所有的花,记录下最大值和最小值,然后相减,第一个问题的答案就出来啦!

最大差值 = max_b - min_b

第二步:计算组合数量

这部分稍微需要动动小脑筋,要分成两种情况来讨论哦!

情况一:所有花的美丽值都相同 (max_b == min_b)

如果花园里所有的花都一样漂亮,那么 max_bmin_b 就是相等的,最大差值自然就是 0 啦。

在这种情况下,任意挑选两朵花,它们的差值都是 0。所以问题就变成了:从 n 朵花里选出 2 朵,有多少种选法呢?

这是一个经典的组合问题,喵!从 n 个元素中选 2 个的组合数是 C(n, 2)

公式是:n * (n - 1) / 2

注意n 最大可以到 2 * 10^5n * (n - 1) 会非常大,所以计算组合数的时候一定要用 long long 类型来存储,不然数字会“溢出”的,就像牛奶从杯子里满出来一样,喵~

情况二:美丽值有高有低 (max_b > min_b)

如果花园里的花美丽值不完全相同,那么要达到最大差值 max_b - min_b,我们必须这么选:

  • 一朵花的美丽值必须是 min_b
  • 另一朵花的美丽值必须是 max_b

所以,我们只需要数一数:

  1. 花园里有多少朵美丽值为 min_b 的花(我们叫它 count_min)。
  2. 花园里有多少朵美丽值为 max_b 的花(我们叫它 count_max)。

根据基础的乘法原理,总的组合数就是这两者数量的乘积啦!

组合数量 = count_min * count_max

同样,这个乘积也可能很大,也要用 long long 来存哦!

代码实现喵

下面是 C++ 的代码实现,我已经加上了可爱的注释,方便你理解每一行都在做什么,喵~

cpp
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 使用高速 I/O,让程序跑得像小猫一样快,喵~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    // 用一个 vector 来装下所有花的美丽值
    std::vector<int> b(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> b[i];
    }

    // 像小猫寻找最舒适的角落一样,我们来寻找最大值和最小值
    int min_b = b[0];
    int max_b = b[0];
    for (int i = 1; i < n; ++i) {
        if (b[i] < min_b) {
            min_b = b[i];
        } else if (b[i] > max_b) {
            max_b = b[i];
        }
    }

    // 计算最大差值,记得用 long long 哦
    long long max_diff = static_cast<long long>(max_b) - min_b;
    long long ways;

    if (max_diff == 0) {
        // 情况一:所有花的美丽值都一样
        // 组合数是 n * (n - 1) / 2
        ways = static_cast<long long>(n) * (n - 1) / 2;
    } else {
        // 情况二:美丽值有高有低
        // 数一数最小值和最大值的花各有几朵
        long long count_min = 0;
        long long count_max = 0;
        for (int val : b) {
            if (val == min_b) {
                count_min++;
            } else if (val == max_b) {
                count_max++;
            }
        }
        // 把它们的数量乘起来就是答案啦!
        ways = count_min * count_max;
    }

    // 把结果告诉 Pashmak 吧!
    std::cout << max_diff << " " << ways << '\n';

    return 0;
}

知识点总结喵

这道题虽然不难,但包含了一些很重要的基础知识点哦!

  1. 最大/最小值查找: 遍历数组找到最大值和最小值,这是每个程序员都必须掌握的基本功,喵。
  2. 分类讨论: 这是解决问题的关键!根据最大值和最小值是否相等,我们采用了两种不同的计数策略,让逻辑变得清晰。
  3. 组合数学: 在所有元素都相同的情况下,计算组合数 C(n, 2)
  4. 乘法原理: 在最大值和最小值不同的情况下,用乘法原理计算总方案数。
  5. 数据类型选择: 注意到结果可能超过 int 的范围,需要使用 long long 来避免溢出。这是写代码时要养成的好习惯,可以避免很多奇怪的错误,喵~

好啦,这道题就愉快地解决啦!是不是感觉很简单呢?只要理清思路,一步一步来,就没有解不开的谜题。希望这次的讲解对你有帮助哦!下次再见啦,喵~

Released under the MIT License.