Skip to content

喵~ 各位好呀,我是你们的小助手猫娘!今天我们要一起来看一道非常可爱的题目,关于分硬币的捏。别看它只是个 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 整除,对不对呀?

  1. 计算总硬币数: 一开始,三姐妹总共有 a + b + c 枚硬币。Polycarp 又带来了 n 枚。所以,当他把所有硬币分完后,硬币的总数就是 a + b + c + n

  2. 第一个条件:总数必须能被 3 整除 为了让三个人最后数量相等,那么这个总数 a + b + c + n 必须是 3 的倍数。如果连总数都不能被 3 整除,那无论怎么分,都不可能让三个人平分呀。所以,如果 (a + b + c + n) % 3 != 0,那肯定就是 "NO" 啦。

  3. 第二个条件:每个人的最终数量必须足够多 如果总数可以被 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 比她们中任何一个人的初始数量还要少,那说明那个本来硬币多的人需要“交出”硬币才能达到平衡,这是做不到的。

所以,我们的解题方法就很清晰啦:

  1. 计算总和 total_sum = a + b + c + n
  2. 检查 total_sum 是否能被 3 整除。如果不能,输出 "NO"。
  3. 如果能,计算出目标数量 target = total_sum / 3
  4. 检查 target 是否大于等于 abc 中的最大值。如果满足,输出 "YES"。
  5. 否则,输出 "NO"。

是不是很简单呀?喵~


题解代码

下面是 C++ 的实现代码,本喵给加上了可爱的注释哦~

cpp
#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;
}

相关知识点介绍

这道题虽然简单,但涉及到的知识点在编程竞赛中可是基础中的基础呢,要好好掌握哦!

  1. 模运算 (Modulo Operation) 代码中的 total_sum % 3 就是模运算。它的作用是计算一个数除以另一个数后的余数。在这里,total_sum % 3 != 0 就是在判断 total_sum 除以 3 的余数是不是不为 0,以此来检查它是否能被 3 整除。这是判断整除性的标准方法,非常常用!

  2. 逻辑推理与寻找必要条件 解决这类问题的核心在于找到问题成立的必要条件。就像我们分析的那样,要实现目标,必须满足两个条件:

    • 总数能被 3 整除。
    • 最终目标值不小于任何一个初始值。 只有当所有必要条件都满足时,问题才有解。这种从结果倒推条件的思维方式在解题时非常重要。
  3. std::max 函数 在 C++ 中,<algorithm> 头文件里的 std::max 是一个超级方便的函数。std::max({a, b, c}) 可以直接从一个列表(initializer list)中找出最大的那个元素。这比我们自己写 if 语句来比较要简洁多啦。

  4. 数据类型 long long 注意到题目中的 a, b, c, n 最大可以到 10^8。它们加起来的和 a+b+c+n 可能会超过 2 * 10^9,这个数值超过了普通 int 类型能表示的范围(通常是 2 * 10^9 左右)。为了防止数据溢出导致计算错误,我们使用了 long long 类型,它可以表示更大的整数范围,这样就安全多啦,喵~

好啦,这次的题解就到这里啦!希望对你有帮助哦!下次再见,喵~ (ฅ'ω'ฅ)

Released under the MIT License.