这道题是一道求输入分数之和的题,可能有负数。如果答案为假分数,则要按照带分数的形式输出,整数则按照整数输出,否则按照真分数输出。
注:
- 负数无需特殊处理,只需要当作分子为负数的分数即可
- 数据范围为int,两个分母相乘时,最大可以达到long long,所以如果使用int会溢出,得到“error”
- 计算最大公约数时,注意分子分母绝对值的公约数,否则数据会错误
- 且必须在每一步加法后均进行约分,否则若等全部加完后才进行约分就会溢出
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long l;
l gys(l a, l b)
{
return b == 0 ? a : gys(b, a % b);
}
struct fraction
{
l numerator, denominator;//分子,分母
};
fraction reduc(fraction result)//化简
{
if (result.denominator < 0)//分母为负数,令分子和分母都变为相反数
{
result.numerator = -result.numerator;
result.denominator = -result.denominator;
}
if (result.numerator == 0)
{
result.denominator = 1;
}
else
{
l d = gys(abs(result.numerator), abs(result.denominator));
result.numerator /= d;
result.denominator /= d;
}
return result;
}
fraction add(fraction f1, fraction f2)//分数f1与分数f2相加
{
fraction result;
result.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator;//分数和的分子
result.denominator = f1.denominator * f2.denominator;//分数和的分母
return reduc(result);
}
void showresult(fraction r)
{
reduc(r);
if (r.denominator == 1)
cout << r.numerator << endl;//输出整数
else if (abs(r.numerator) > r.denominator)
{
printf("%lld %lld/%lld\n", r.numerator / r.denominator, abs(r.numerator) % r.denominator, r.denominator);
}
else
{
printf("%lld/%lld\n", r.numerator, r.denominator);
}
}
int main()
{
int n;
cin >> n;
fraction sum, temp;
sum.numerator = 0;
sum.denominator = 1;
for (int i = 0; i < n; i++)
{
scanf("%lld/%lld", &temp.numerator, &temp.denominator);
sum = add(sum, temp);
}
showresult(sum);
return 0;
}
这里使用的是scanf,vs上可以使用scanf_s避免溢出,scanf在很多编译器上已经淘汰,但是在pat上还可以使用,如果使用cin,我不知道怎么处理表达式的关系,若每个表达式均用一个变量赋值后再输入输出未免太过冗余,待以后学习后再来优化。
以下是测试结果: