第三部分 第二题——《晚宴》第一幕美食晚宴开始了1、有一天小明参加了一场五星级晚宴。桌子上摆着很多菜。每道菜都有一个美味度。1例如3 5 7 35 1052主持人宣布了一个规则小明只能选两道菜而且必须是两道菜。而且还有一个特殊要求这两道菜必须互质3小明的目标是按照规则选让两道菜的美味度之和最大。第二幕什么叫互质1、有的学生一看到互质脑子一片空白。其实非常简单。2、老师拿出几个数字。第一组3 5最大公约数gcd(3,5) 1所以互质可以一起吃。第二组6 9最大公约数3不是1所以不能一起选。第三组8 15最大公约数1是可以的。3、互质 gcd1以后看到互质脑子立刻翻译成gcd(a,b)1这是学习数论最重要的结论之一。第三幕先不要写程序1、先看样例。3 5 7 35 1052、我们先人工找一下。1第一对3 5互质。和是82第二对3 7互质。和是103第三对35 7最大公约数7失败。4第四对35 105最大公约数35失败。5第五对5 35最大公约数5失败。6继续……最后发现3 35互质。和38这是最大的。7所以答案38和样例一致。第四幕本题能用暴力枚举吗可以1、如果有5道菜。3 5 7 35 1052、每两道菜都试一次。3 5 3 7 3 35 3 105 5 7 5 35 ……所有组合。都检查。3、暴力枚举的时间复杂度O(N^2)本题中 2 n 1000,完全没问题。第五幕使用两层循环1、外层循环第一个数2、内层循环第二个数3、代码for(i) for(j)就是所有组合。第六幕如何更新答案1、我们先定义一个ans开始02、现在第一组。3 5合法。和83、于是ans 84、下一组3 7合法。10比8大。更新。ans 105、于是程序就是if(gcd(...)1) ansmax(ans,ab);答案就按照我们的要求更新了。第七幕重点要写gcd 函数1、因为互质判断的是最大公约数。2、所以要写gcd函数来求最大公约数。3、使用欧几里得算法int gcd(int a,int b) { if(b0) return a; return gcd(b,a%b); }第八幕完整代码#include iostream #include algorithm using namespace std; int gcd(int a,int b) { if(b0) return a; return gcd(b,a%b); } int main() { int n; cinn; int a[1010]; for(int i0;in;i) cina[i]; int ans0; for(int i0;in;i) { for(int ji1;jn;j) { if(gcd(a[i],a[j])1) { ansmax(ans,a[i]a[j]); } } } coutansendl; return 0; }利用两层循环枚举所有两两组合判断是否互质如果互质就更新最大答案。第九幕程序复杂度分析1、题目中n 10002、两层循环1000×1000 ≈100万3、每次gcd复杂度O(logV)4、总复杂度O(n² logV)对于本题的数据范围是完全可以通过的。本题要掌握的知识★★★★★这道题考点首先就是要掌握gcd()函数还要有正确的思维流程① 枚举所有可能方案 ↓ ② 判断是否合法 ↓ ③ 如果合法 ↓ ④ 更新最优答案朴素算法模板遇到类似从很多方案中找到最优方案的问题可以想到下面这个模板ans 初始值; for(枚举所有方案) { if(方案合法) { ans max(ans, 当前方案); } }这道《晚宴》就是这个基础模板的应用。