洛谷P1572题解析:分数计算的优化解法与代码实现

一、题目解读
洛谷P1572题要求处理包含分数与运算符的输入表达式,计算并输出最简分数结果。题目难点在于:
1)解析混合的分数与整数表达式;
2)分数化简至最简形式;
3)处理连续加减运算。
需结合数学算法与编程逻辑,实现高效计算。
二、解题思路
1. 模块化设计:定义分数结构体(分子、分母),封装化简与加法函数,提升代码复用性。
2. GCD优化:利用辗转相除法求最大公约数,简化分数至最简形式(避免分母为负数)。
3. 输入解析:通过循环遍历字符,分离符号、分子、分母,整数视为分母为1的特殊分数。
4. 运算处理:按运算符顺序累加分数,每次加法后调用化简函数,减少重复计算。
三、解题步骤
1. 读取输入:使用getline获取整行表达式,避免空格干扰。
2. 数值分离:
○ 识别符号(+/-),记录数值正负。
○ 提取分子:连续数字拼接成整数。
○ 若遇到'/',继续提取分母;否则默认分母为1。
3. 构建分数列表:将解析的分数存入vector,同时记录运算符。
4. 循环计算:
○ 初始化结果分数为第一个分数。
○ 遍历后续分数与运算符,根据符号执行加法或减法(转化为加法与负数)。
○ 每次运算后调用simplify()化简。
5. 输出结果:最终分数化简后输出分子与分母。
四、代码与注释
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
// 计算最大公约数(辗转相除法)
int gcd(int a, int b) {
return b == 0? a : gcd(b, a % b); // 递归终止条件与迭代
}
// 分数结构体
struct Fraction {
int numerator; // 分子
int denominator; // 分母
// 化简分数:通过GCD去除公约数,确保分母为正
void simplify() {
int common = gcd(abs(numerator), abs(denominator));
numerator /= common;
denominator /= common;
// 修正符号(分母始终为正)
if (denominator < 0) {
numerator *= -1;
denominator *= -1;
}
}
// 分数加法(核心运算)
Fraction operator+(const Fraction& other) const {
Fraction result;
// 通分后相加:分子 = 分子1*分母2 + 分子2*分母1
result.numerator = numerator * other.denominator + other.numerator * denominator;
result.denominator = denominator * other.denominator;
// 运算后立即化简
result.simplify();
return result;
}
};
int main() {
string s;
getline(cin, s); // 输入整行表达式
vector<Fraction> fractions; // 存储解析后的分数
vector<char> operators; // 存储运算符(+/-)
// 解析输入:逐字符分离符号、分子、分母
int i = 0;
while (i < s.size()) {
// 解析符号(可选)
int sign = 1;
if (s[i] == '-') {
sign = -1; // 负数标记
i++;
} else if (s[i] == '+') {
i++; // 跳过正号
}
// 解析分子(连续数字)
int num = 0;
while (i < s.size() && isdigit(s[i])) {
num = num * 10 + (s[i] - '0'); // 字符转数字
i++;
}
num *= sign; // 应用符号
// 解析分母(存在'/'时)
if (i < s.size() && s[i] == '/') {
i++; // 跳过'/'
int den = 0;
while (i < s.size() && isdigit(s[i])) {
den = den * 10 + (s[i] - '0');
i++;
}
fractions.push_back({num, den}); // 存入分数
} else {
// 整数视为分母为1的分数
fractions.push_back({num, 1});
}
// 记录运算符(后续处理)
if (i < s.size() && (s[i] == '+' || s[i] == '-')) {
operators.push_back(s[i]); // 存储符号
i++; // 跳过运算符
}
}
// 计算最终结果
Fraction result = fractions[0]; // 初始化为第一个分数
for (int j = 1; j < fractions.size(); j++) {
// 根据运算符执行加法(减法转为加法负数)
if (operators[j-1] == '-') {
result = result + (-fractions[j]); // 负数分数
} else {
result = result + fractions[j];
}
}
// 输出结果
if (result.denominator == 1) {
cout << result.numerator << endl;
} else {
cout << result.numerator << "/" << result.denominator << endl;
}
return 0;
}五、总结
本文通过自定义分数结构体和GCD算法,实现了洛谷P1572题的简洁解法。核心在于将分数运算模块化,结合输入解析与符号处理,确保结果准确且符合最简要求。代码结构清晰,适用于算法学习与竞赛实践,同时通过关键词优化提升
原创内容 转载请注明出处






