喵~ 各位好呀,我是你们的小助手猫娘!今天我们要一起来看一道非常可爱的题目,关于分硬币的捏。别看它只是个 Div. 2 的 A 题,里面可是藏着一些简单又重要的小心思哦。让我们开始吧!
A. Collecting Coins
题目大意
这道题是说,有一个叫 Polycarp 的好心人,他有三个妹妹,分别叫 Alice, Barbara 和 Cerene。她们本来各自有 a
, b
, c
枚硬币。现在 Polycarp 从外面带回来了 n
枚新硬币,他想把这 n
枚硬幣全部分给三个妹妹。
他的目标是,分配完之后,三个妹妹手里的硬币数量要变得一模一样多!也就是说,如果他给了 Alice A
枚,Barbara B
枚,Cerene C
枚(其中 A+B+C = n
),那么最终要满足 a+A = b+B = c+C
。
我们需要判断,Polycarp 能不能做到这件事呢?如果可以,就输出 "YES",不然就输出 "NO",喵~
解题思路
这道题其实是一个逻辑推理题,不需要什么复杂的算法,只要我们想清楚几个关键点就好啦。
首先,我们来想想,如果最后三个妹妹的硬币数量要相等,那么她们总共的硬币数量必须能被 3 整除,对不对呀?
计算总硬币数: 一开始,三姐妹总共有
a + b + c
枚硬币。Polycarp 又带来了n
枚。所以,当他把所有硬币分完后,硬币的总数就是a + b + c + n
。第一个条件:总数必须能被 3 整除 为了让三个人最后数量相等,那么这个总数
a + b + c + n
必须是 3 的倍数。如果连总数都不能被 3 整除,那无论怎么分,都不可能让三个人平分呀。所以,如果(a + b + c + n) % 3 != 0
,那肯定就是 "NO" 啦。第二个条件:每个人的最终数量必须足够多 如果总数可以被 3 整除,那么我们就可以算出每个人最终应该拥有的硬币数量了,就是
target = (a + b + c + n) / 3
。 但是,这里有一个很重要的限制喵:Polycarp 只能给妹妹们硬币,不能从她们手里拿走。这意味着,每个妹妹最终的硬币数target
,必须大于或等于她原来的硬币数。- Alice 最终要有
target
枚,所以target >= a
。 - Barbara 最终要有
target
枚,所以target >= b
。 - Cerene 最终要有
target
枚,所以target >= c
。
这三个条件要同时满足,其实就等价于说,
target
必须大于或等于她们三人中初始硬币数最多的那个。也就是target >= max(a, b, c)
。如果target
比她们中任何一个人的初始数量还要少,那说明那个本来硬币多的人需要“交出”硬币才能达到平衡,这是做不到的。- Alice 最终要有
所以,我们的解题方法就很清晰啦:
- 计算总和
total_sum = a + b + c + n
。 - 检查
total_sum
是否能被 3 整除。如果不能,输出 "NO"。 - 如果能,计算出目标数量
target = total_sum / 3
。 - 检查
target
是否大于等于a
、b
和c
中的最大值。如果满足,输出 "YES"。 - 否则,输出 "NO"。
是不是很简单呀?喵~
题解代码
下面是 C++ 的实现代码,本喵给加上了可爱的注释哦~
#include <iostream>
#include <algorithm>
#include <vector>
// 这个函数是用来解决单个测试用例的,喵~
void solve() {
long long a, b, c, n;
std::cin >> a >> b >> c >> n;
// 先把所有硬币加起来,看看总共有多少
long long total_sum = a + b + c + n;
// 条件一:如果总数不能被3整除,那肯定没法平分啦
if (total_sum % 3 != 0) {
std::cout << "NO\n";
return;
}
// 如果能被3整除,算出每个人最后应该有多少硬币
long long target_coins = total_sum / 3;
// 条件二:每个人最终的硬币数,不能比她原来的还少呀!
// 所以,目标数量必须大于等于她们三个中原来最多的那个人的数量
long long max_initial = std::max({a, b, c});
if (target_coins >= max_initial) {
// 两个条件都满足,太棒啦!可以做到!
std::cout << "YES\n";
} else {
// 目标数量太小了,做不到的,呜
std::cout << "NO\n";
}
}
int main() {
// 这两行是为了让输入输出快一点,对付好多好多测试用例的时候很有用哦
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int t;
std::cin >> t; // 读取有几组测试
while (t--) {
solve();
}
return 0;
}
相关知识点介绍
这道题虽然简单,但涉及到的知识点在编程竞赛中可是基础中的基础呢,要好好掌握哦!
模运算 (Modulo Operation) 代码中的
total_sum % 3
就是模运算。它的作用是计算一个数除以另一个数后的余数。在这里,total_sum % 3 != 0
就是在判断total_sum
除以 3 的余数是不是不为 0,以此来检查它是否能被 3 整除。这是判断整除性的标准方法,非常常用!逻辑推理与寻找必要条件 解决这类问题的核心在于找到问题成立的必要条件。就像我们分析的那样,要实现目标,必须满足两个条件:
- 总数能被 3 整除。
- 最终目标值不小于任何一个初始值。 只有当所有必要条件都满足时,问题才有解。这种从结果倒推条件的思维方式在解题时非常重要。
std::max
函数 在 C++ 中,<algorithm>
头文件里的std::max
是一个超级方便的函数。std::max({a, b, c})
可以直接从一个列表(initializer list)中找出最大的那个元素。这比我们自己写if
语句来比较要简洁多啦。数据类型
long long
注意到题目中的a, b, c, n
最大可以到10^8
。它们加起来的和a+b+c+n
可能会超过2 * 10^9
,这个数值超过了普通int
类型能表示的范围(通常是2 * 10^9
左右)。为了防止数据溢出导致计算错误,我们使用了long long
类型,它可以表示更大的整数范围,这样就安全多啦,喵~
好啦,这次的题解就到这里啦!希望对你有帮助哦!下次再见,喵~ (ฅ'ω'ฅ)