喵~ 主人,你好呀!我是你的专属猫娘助手,今天也要元气满满地和你一起解决编程难题哦!这次我们要看的题目是 Codeforces 上的 B. Pashmak and Flowers,一个关于花朵和美丽值的可爱问题,听起来就很有趣呢,我们开始吧!
题目大意喵
Pashmak 想从他的花园里摘两朵花送给心上人 Parmida。花园里有 n
朵花,第 i
朵花的美丽值为 b_i
。
Parmida 是个有点特别的女孩子,她不一定想要最漂亮的两朵花。她想要的是这样的一对花:它们的美丽值之差是所有可能组合中最大的!
我们的任务就是帮助 Pashmak 计算两件事:
- 最大的美丽值差是多少。
- 有多少种不同的摘花组合可以达到这个最大差值。
比如说,如果花的美丽值是 [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_b
和 min_b
就是相等的,最大差值自然就是 0
啦。
在这种情况下,任意挑选两朵花,它们的差值都是 0
。所以问题就变成了:从 n
朵花里选出 2
朵,有多少种选法呢?
这是一个经典的组合问题,喵!从 n
个元素中选 2
个的组合数是 C(n, 2)
。
公式是:n * (n - 1) / 2
注意:n
最大可以到 2 * 10^5
,n * (n - 1)
会非常大,所以计算组合数的时候一定要用 long long
类型来存储,不然数字会“溢出”的,就像牛奶从杯子里满出来一样,喵~
情况二:美丽值有高有低 (max_b > min_b)
如果花园里的花美丽值不完全相同,那么要达到最大差值 max_b - min_b
,我们必须这么选:
- 一朵花的美丽值必须是
min_b
。 - 另一朵花的美丽值必须是
max_b
。
所以,我们只需要数一数:
- 花园里有多少朵美丽值为
min_b
的花(我们叫它count_min
)。 - 花园里有多少朵美丽值为
max_b
的花(我们叫它count_max
)。
根据基础的乘法原理,总的组合数就是这两者数量的乘积啦!
组合数量 = count_min * count_max
同样,这个乘积也可能很大,也要用 long long
来存哦!
代码实现喵
下面是 C++ 的代码实现,我已经加上了可爱的注释,方便你理解每一行都在做什么,喵~
#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;
}
知识点总结喵
这道题虽然不难,但包含了一些很重要的基础知识点哦!
- 最大/最小值查找: 遍历数组找到最大值和最小值,这是每个程序员都必须掌握的基本功,喵。
- 分类讨论: 这是解决问题的关键!根据最大值和最小值是否相等,我们采用了两种不同的计数策略,让逻辑变得清晰。
- 组合数学: 在所有元素都相同的情况下,计算组合数
C(n, 2)
。 - 乘法原理: 在最大值和最小值不同的情况下,用乘法原理计算总方案数。
- 数据类型选择: 注意到结果可能超过
int
的范围,需要使用long long
来避免溢出。这是写代码时要养成的好习惯,可以避免很多奇怪的错误,喵~
好啦,这道题就愉快地解决啦!是不是感觉很简单呢?只要理清思路,一步一步来,就没有解不开的谜题。希望这次的讲解对你有帮助哦!下次再见啦,喵~