题解:洛谷 P17011 晚宴

【题目来源】

洛谷:P17011 [GESP202606 五级] 晚宴 - 洛谷

【题目描述】

小明去参加晚宴。晚宴中有 \(n\) 个菜肴,每个菜肴都有一个美味度,第 \(i\) 个菜肴的美味度为 \(v_i\)

晚宴规定小明只能恰好选取两道菜肴,并且这两道菜肴的美味度必须要互质(即最大公约数为 \(1\))。

请帮助小明选取两道菜肴,使得两道菜肴美味度之和最大。

【输入】

输入 \(2\) 行,

第一行为一个正整数 \(n\),表示菜肴的个数;

第二行为 \(n\) 个整数 \(v_1, v_2, \cdots, v_n\) 表示菜肴的美味度,整数之间以空格分隔。

【输出】

输出一个整数,表示两道互质菜肴美味度之和的最大值。

【输入样例】

5
3 5 7 35 105

【输出样例】

38

【核心思想】

  1. 问题分析:给定 \(n\) 个菜肴的美味度 \(v_1, v_2, \ldots, v_n\),要求恰好选取两道互质(\(\gcd(v_i, v_j) = 1\))的菜肴,使得美味度之和最大。这是一个枚举 + 最大公约数问题,核心在于遍历所有不重复的菜对并筛选满足互质条件的最大和。

  2. 算法选择

    • 双重枚举:枚举所有 \(C_n^2 = \frac{n(n-1)}{2}\) 种菜对组合
    • 最大公约数判定:利用 __gcd 函数判断两数是否互质
  3. 关键步骤

    • 读入数据:读取 \(n\) 和数组 \(a[1..n]\)
    • 枚举菜对\(i\)\(1\)\(n-1\)\(j\)\(i+1\)\(n\)):
      • 计算 \(\gcd(a_i, a_j)\)
      • \(\gcd(a_i, a_j) = 1\),则 \(ans \leftarrow \max(ans, a_i + a_j)\)
    • 输出结果\(ans\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n^2 \cdot \log V)\),其中 \(V\) 为美味度最大值,\(n^2\) 对枚举,每对 \(\gcd\) 计算为 \(O(\log V)\)
    • 空间复杂度:\(O(1)\),仅使用常数额外空间
  5. 枚举与互质判定的核心思想

    • 全枚举保证最优:由于 \(n\) 规模较小(\(n \leq 1000\)),\(O(n^2)\) 的枚举量约为 \(5 \times 10^5\),在可接受范围内,直接遍历所有组合即可找到全局最优解
    • 互质条件筛选:利用欧几里得算法(辗转相除法)计算最大公约数,当 \(\gcd = 1\) 时两数互质,满足题目约束
    • 去重处理:通过 \(j\)\(i+1\) 开始枚举,确保每对菜肴只被考虑一次,避免重复计算和自配对
    • 贪心不可行:不能简单地选取两个最大数,因为它们可能不互质(如样例中的 \(35\)\(105\)\(\gcd = 35\)),必须验证互质条件
    • 适用于约束规模较小、需要遍历所有组合并满足特定数学条件的枚举类问题

【算法标签】

普及- #欧几里得算法

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 1005;                // 常量:最大菜肴数量

int n;                             // n: 菜肴个数
int ans;                           // ans: 两道互质菜肴美味度之和的最大值
int a[N];                          // a[i]: 第 i 个菜肴的美味度

int main()
{
    cin >> n;                      // 读入菜肴个数

    for (int i = 1; i <= n; i++)  // 读入 n 个菜肴的美味度
        cin >> a[i];

    for (int i = 1; i < n; i++)   // 枚举第一道菜
        for (int j = i + 1; j <= n; j++)  // 枚举第二道菜(确保不重复选同一道菜)
            if (__gcd(a[i], a[j]) == 1)  // 如果两道菜的美味度互质
                ans = max(ans, a[i] + a[j]);  // 更新最大美味度之和

    cout << ans << endl;           // 输出最大美味度之和

    return 0;
}

【运行结果】

5
3 5 7 35 105
38

【算法真传】

从一道 GESP 真题出发:聊聊枚举与最大公约数

posted @ 2026-07-07 11:06  团爸讲算法  阅读(56)  评论(0)    收藏  举报