解题过程的小记录,如有错误欢迎指出。
难度:三星(分数的加法运算,化简步骤涉及了求两数的最大公约数,以及分数的表达规则要记住,此处多复习算法笔记的相关篇章)
题目分析
给出一串分数,要求求出它们的和并按照指定格式输出
注意点
- 测试当输出为0的时候能否正常输出
- 采用long long存储分子分母数据
- 找最大公约数的时候注意两个数字都必须转换为绝对值,不然后续的除法化简会因为符号问题出错(如INPUT:2 1/2 -1/3答案应为-1/6)【但是本题的测试点好像没有涉及这一点,我原来没有考虑这一点,也过了,看了晴神的解析才发觉】
我的解题过程
思路
- 输入分数,采用了以string格式输入后找到’/'后用substr进行拆分利用stoll进行转换的方法,进行输入
- 初始化result为一个为0的分数(分子为0,分母为1),在输入后进行化简,直接进行累加
- 写一个累加函数,利用数学公式写出分子分母的变化,返回前进行化简
- 写一个化简函数,其中要用到最大公约数函数
- 写一个输出函数
bug
- 输出真分母的时候,中间的空格问题,有时候输出完实数部分后,后面就没有分母形式了,此时就不需要输出空格(所幸这点可以通过测试用例发现,不然估计自己找也够呛),可以采用flag标记一下是否输出了实数部分然后在输出分数部分前check一下,如果输出过则输出一个空格
- 还是输出函数的问题,输出为0/1的时候,原函数的逻辑下不输出,后来增加了一个if判断分子是否为0,如果是的话直接输出0后返回
代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
typedef long long LL;
struct Fenshu {
LL up, down;//分子分母:如果为0,则up=0,down=1,如果为负则up<0,down>0
};
LL gcd(LL a, LL b) {
a = abs(a);
b = abs(b);
return b == 0 ? a : gcd(b, a%b);
}
Fenshu reduction(Fenshu f) {
if (f.up == 0 || f.down == 0) f.up = 0, f.down = 1;
else if (f.up / f.down < 0) f.up = -abs(f.up), f.down = abs(f.down);
LL g = gcd(f.up, f.down);
f.up = f.up / g;
f.down = f.down / g;
return f;
}
Fenshu addFenshu(Fenshu f1, Fenshu f2) {
Fenshu ans;
ans.up = f1.up*f2.down + f2.up*f1.down;
ans.down = f1.down*f2.down;
return reduction(ans);
}
void prit(Fenshu f) {
if (f.up == 0) {
cout << 0;
return;
}
int flag = 0;
if (abs(f.up) > f.down) {
cout << f.up / f.down;
flag = 1;
}
if (f.up%f.down != 0) {
if (flag == 1) cout << " ";
cout << f.up%f.down << "/" << f.down;
}
}
int main()
{
int n;
cin >> n;
Fenshu result;
result.up = 0, result.down = 1;
for (int i = 0; i < n; i++) {
Fenshu f;
string s;
int pos = 0;
cin >> s;
while (s[pos] != '/') pos++;
f.up = stoll(s.substr(0, pos));
f.down = stoll(s.substr(pos + 1));
result = addFenshu(result, reduction(f));
}
prit(result);
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 如果答案只需要输出实数部分的话,那么结果的分母一定为1,可以通过这个直接输出分子后结束而不需要考虑空格问题,还可以解决0的输出问题
- 本题采用scanf的格式化输入会十分方便,直接得到了分子分母
scanf("%lld/%lld", &a, &b);
- 本题参考晴神的代码比较好,虽然思想一样,但是模板可移植性更高