从值日生问题到算法思维:GESP C++一级编程题的两种解法对比
刚接触编程的同学常常会困惑:为什么一个看似简单的问题会有多种解法?就拿GESP C++一级考试中的"值日生问题"来说,题目描述的是两位同学按不同周期值日,求他们下次同一天值日的日期。这个生活化场景背后,其实隐藏着算法设计中最重要的思维方式——问题抽象与效率优化。
我第一次在考场上遇到这道题时,本能地想到用循环逐个日期判断。后来才知道,这背后涉及数论中的最小公倍数(LCM)概念。更让我惊讶的是,求最小公倍数居然有两种截然不同的思路:一种是直观的循环枚举,另一种则是基于数学定理的辗转相除法。这两种方法在代码实现、执行效率和思维层次上都有显著差异,正好体现了从"解决问题"到"优化方案"的算法进阶之路。
1. 问题建模与基础解法
1.1 生活问题到数学抽象
值日生问题的核心是找出两个周期首次重合的时间点。假设小杨每4天值日一次,小红每6天值日一次,他们今天一起值日后,下次共同值日就是第12天。这个12正是4和6的最小公倍数。
用数学表达式描述就是:
给定两个正整数m和n,求最小的正整数k,使得k是m的倍数且k是n的倍数
提示:初学者常犯的错误是直接返回m*n,这在m和n互质时成立(如3和5的最小公倍数是15),但当两数有公约数时(如4和6)就会出错。
1.2 循环枚举法实现
最直观的解法是从较大的数开始逐个检查,直到找到符合条件的数:
#include <iostream>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
int start = max(m, n);
int end = m * n;
for(int i = start; i <= end; i++) {
if(i % m == 0 && i % n == 0) {
cout << i;
break;
}
}
return 0;
}
这种方法的特点非常明显:
-
优点:
- 逻辑简单直接,容易理解
- 不需要额外的数学知识
- 代码实现难度低
-
缺点:
- 效率随输入值增大而显著降低
- 最坏情况下需要循环m*n次(当m和n互质时)
- 对大数处理性能较差

623

被折叠的 条评论
为什么被折叠?



