Do You Know Your ABCs?

GitHub跳转原题关系图返回列表

排序后最小两个数是 A、B,最大数是 A+B+C,直接相减得到 C。

OJ: usaco

题目 ID: 1059

难度:入门

标签:数学排序枚举

日期: 2026-07-11 13:52

题意

有三个正整数 ABC,满足 A<=B<=CA <= B <= C

现在给出下面 7 个数的乱序结果:

text
A, B, C, A+B, A+C, B+C, A+B+C

要求还原并输出 A B C

思路

朴素验证

可以先写一个直接枚举的版本:枚举输入中的三个值作为 ABC,生成 7 个数后排序,和输入排序后的多重集合比较。

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-11 13:52
 * update_at: 2026-07-11 13:54
 */
// brute.cpp:小数据暴力解,用来帮助理解题意并辅助对拍。
#include <bits/stdc++.h>
using namespace std;

long long x[10];      // 输入的 7 个数
long long target[10]; // 排序后的输入多重集合
long long cur[10];    // 某组 A,B,C 生成出的 7 个数

bool same_multiset() {
    for (int i = 0; i < 7; i++) {
        if (cur[i] != target[i]) {
            return false;
        }
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    for (int i = 0; i < 7; i++) {
        cin >> x[i];
        target[i] = x[i];
    }
    sort(target, target + 7);

    // 暴力枚举三个秘密数字分别等于输入中的哪个值,再检查能否生成同一个多重集合。
    for (int i = 0; i < 7; i++) {
        for (int j = 0; j < 7; j++) {
            for (int k = 0; k < 7; k++) {
                long long A = x[i];
                long long B = x[j];
                long long C = x[k];
                if (!(A <= B && B <= C)) {
                    continue;
                }

                cur[0] = A;
                cur[1] = B;
                cur[2] = C;
                cur[3] = A + B;
                cur[4] = A + C;
                cur[5] = B + C;
                cur[6] = A + B + C;
                sort(cur, cur + 7);

                if (same_multiset()) {
                    cout << A << ' ' << B << ' ' << C << '\n';
                    return 0;
                }
            }
        }
    }

    return 0;
}

这个暴力能直接体现题意:我们要找的是能生成同一个多重集合的三元组。由于只有 7 个输入值,枚举候选值本身也很小;但正式解法可以更直接。

关键观察

把 7 个数排序。因为 ABC 都是正整数,任意两个数的和一定不小于其中的单个数,三个数的和一定最大。

又因为题目给出 A<=B<=CA <= B <= C,所以:

text
排序后第 1 个数 = A
排序后第 2 个数 = B
排序后最后一个数 = A+B+C

于是:

text
C = (A+B+C) - A - B

所以只需要排序一次,就能得到答案。

代码

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-11 13:52
 * update_at: 2026-07-11 13:54
 */
#include <bits/stdc++.h>
using namespace std;

long long a[10]; // 输入的 7 个数

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    for (int i = 0; i < 7; i++) {
        cin >> a[i];
    }

    sort(a, a + 7);

    long long A = a[0];
    long long B = a[1];
    long long C = a[6] - A - B;

    cout << A << ' ' << B << ' ' << C << '\n';

    return 0;
}

复杂度

只排序 7 个数,时间复杂度可以看作 O(1)O(1)

只保存 7 个数,空间复杂度为 O(1)O(1)

总结

这题的重点是保留“正整数”和 A<=B<=CA <= B <= C 这两个条件。

它们让排序后的最小两个值和最大值都有确定含义,因此可以直接从极值推出 ABC