1. 题目背景与核心挑战
这道来自天梯赛的L1-009题目,表面上看是一个简单的求和问题,但实际上暗藏玄机。作为一名经历过多次算法竞赛的老手,我第一眼就看出这道题考察的是对分数运算的系统性理解。新手容易犯的错误是直接用浮点数计算,但题目明确要求以有理数形式处理,这就涉及到分数运算的完整流程。
分数运算在计算机中的处理远比整数复杂,主要体现在三个方面:首先需要处理通分问题,这要求我们掌握最小公倍数(LCM)的计算;其次每次运算后都需要约分,这就离不开最大公约数(GCD)算法;最后还要考虑数值溢出问题,因为连续的分数运算可能导致分子分母急剧增大。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路详解
2.1 分数运算的基本原理
分数加减法的数学原理其实很简单:a/b + c/d = (ad + bc)/bd。但在实际编程实现时,直接这样计算会导致分母迅速膨胀,很容易超出数据类型的表示范围。更合理的做法是先计算分母的最小公倍数,将两个分数转换为同分母后再相加。
这里就引出了两个核心算法:
- 最大公约数(GCD):用于分数约分
- 最小公倍数(LCM):用于分数通分
2.2 最大公约数算法实现
辗转相除法(欧几里得算法)是计算GCD的最高效方法。它的基本原理是:gcd(a,b) = gcd(b, a mod b)。这个算法的时间复杂度是O(log min(a,b)),效率非常高。
在C/C++中实现时需要注意几点:
- 处理负数:题目允许分子为负,所以GCD计算时要先取绝对值
- 数据类型:必须使用long long,因为int可能溢出
- 边界条件:当b为0时,a就是GCD
2.3 最小公倍数的计算技巧
LCM可以通过GCD推导出来:lcm(a,b) = a*b/gcd(a,b)。但直接这样计算存在溢出风险,更安全的做法是先除后乘:a/gcd(a,b)*b。
在实际编程中,我建议将LCM单独封装成函数,这样代码更清晰,也便于复用。
3. 代码实现与优化
3.1 C语言版本详解
C语言的实现更基础,适合理解底层原理。核心逻辑分为几个步骤:
- 初始化总和为0/1
- 逐个读取分数,每次读取后:
- 计算当前总和与新分数的公分母(LCM)
- 将两个分数转换为同分母
- 分子相加
- 立即
