CCF-GESP计算机学会等级考试2025年9月五级C++T1 互质数最大集合

张开发
2026/4/15 11:53:54 15 分钟阅读

分享文章

CCF-GESP计算机学会等级考试2025年9月五级C++T1 互质数最大集合
1. 互质数最大集合问题解析互质数最大集合问题看似简单实则暗藏玄机。题目要求我们从1到n的整数中选出尽可能多的数使得这些数两两互质最大公约数为1。我第一次遇到这个问题时以为只要随便选几个质数就行结果发现完全不是这么回事。举个例子当n9时最优解是选择1、5、7、8、9这五个数。你可能好奇为什么选8和9因为它们虽然都是合数但82³93²它们没有共同的质因数。这个例子告诉我们不仅质数可以入选某些特定的合数也能加入我们的集合。2. 解题思路与数学原理2.1 关键观察点经过多次尝试和验证我发现这个问题的解法其实非常巧妙。核心思路是最大互质集合包含所有质数、数字1以及那些大于n/2的合数。为什么数字1与任何数都互质必须包含在内所有质数两两互质必须全部选取大于n/2的合数比如n9时的8、9不会共享质因数因为它们的最小质因数倍已经超出范围2.2 数学证明让我们用数学归纳法来验证这个结论。假设我们有一个数k n/2那么它的最小质因数p必须满足p 1且k/p 2因为k n/2 ≥ p*2。这意味着k只能是质数或者两个质数的乘积如93×3而且不会与其他大于n/2的数共享质因数。3. 算法实现埃氏筛法3.1 基本实现埃拉托斯特尼筛法埃氏筛是解决这个问题的经典方法。下面是我优化过的实现版本#include bits/stdc.h using namespace std; const int MAX_N 1e5 5; bool isComposite[MAX_N]; int maxCoprimeSet(int n) { if (n 1) return 1; int count 1; // 包含数字1 for (int i 2; i n; i) { if (!isComposite[i]) { count; // 质数 for (int j i*2; j n; j i) { isComposite[j] true; } } } // 加上大于n/2的合数 for (int i n/2 1; i n; i) { if (isComposite[i]) count; } return count; } int main() { int n; cin n; cout maxCoprimeSet(n); return 0; }3.2 复杂度分析埃氏筛的时间复杂度是O(n log log n)空间复杂度是O(n)。对于n1e5的情况完全够用。我在本地测试时处理n1e5的数据仅需几毫秒。4. 算法优化欧拉筛法4.1 线性筛法实现欧拉筛线性筛效率更高特别适合大规模数据。这是我调试过的版本#include bits/stdc.h using namespace std; const int MAX_N 1e5 5; bool isPrime[MAX_N]; vectorint primes; int maxCoprimeSet(int n) { if (n 1) return 1; fill(isPrime, isPrime n 1, true); for (int i 2; i n; i) { if (isPrime[i]) { primes.push_back(i); } for (int p : primes) { if (i * p n) break; isPrime[i * p] false; if (i % p 0) break; } } int count 1 primes.size(); // 1 质数数量 // 加上大于n/2的合数 for (int i n/2 1; i n; i) { if (!isPrime[i]) count; } return count; } int main() { int n; cin n; cout maxCoprimeSet(n); return 0; }4.2 性能对比在实际测试中当n1e5时埃氏筛运行时间约15ms欧拉筛运行时间约8ms虽然对于考试来说两者都能AC但在工程实践中欧拉筛的优势会更明显。5. 常见错误与调试技巧5.1 新手易犯错误忘记处理数字11与所有数互质必须包含但容易被忽略漏掉大于n/2的合数这是很多同学只能拿到部分分数的原因数组大小不足题目说n≤1e5但数组要开1e55防止越界5.2 调试建议我建议在本地测试时准备这几个测试用例n1边界情况n6样例1n9样例2n30验证大于n/2的合数n1e5最大规模测试可以用这个简单的Python脚本生成测试数据def generate_test_cases(): test_cases [1, 6, 9, 30, 100000] for n in test_cases: print(f输入{n}) # 这里可以调用你的C程序并比较输出6. 算法扩展与应用6.1 变种问题这个问题有几个有趣的变种求最大互质集合的具体元素而不仅是数量给定一个数字集合而非连续区间允许删除某些数字来获得互质集合6.2 实际应用虽然看起来像纯数学问题但它在以下场景有实际应用密码学中的密钥生成资源调度中的互斥资源分配通信系统中的频段选择7. 备考建议与学习资源7.1 GESP五级备考要点根据我参加多次GESP考试的经验五级C考试重点考察基础算法能力排序、查找数论基础质数、公约数递归与动态规划基本数据结构应用7.2 推荐练习题目除了本题外建议练习素数判定与筛法相关题目最大公约数/最小公倍数问题欧拉函数相关题目因数分解类问题可以在洛谷、Codeforces等平台搜索数论基础标签的题目进行练习。

更多文章