7-5 N个数求和

本题的要求很简单,就是求N个数字的和。麻烦的是,这些数字是以有理数分子/分母的形式给出的,你输出的和也必须是有理数的形式。

输入格式:

输入第一行给出一个正整数N(≤100)。随后一行按格式a1/b1 a2/b2 …给出N个有理数。题目保证所有分子和分母都在长整型范围内。另外,负数的符号一定出现在分子前面。

输出格式:

输出上述数字和的最简形式 —— 即将结果写成整数部分 分数部分,其中分数部分写成分子/分母,要求分子小于分母,且它们没有公因子。如果结果的整数部分为0,则只输出分数部分。

输入样例1:

5
2/5 4/15 1/30 -2/60 8/3

输出样例1:

3 1/3

输入样例2:

2
4/3 2/3

输出样例2:

2

输入样例3:

3
1/3 -1/6 1/8

输出样例3:

7/24

思路:

  • 分数用结构体存储
  • 每输入一个分数,累加,约分
  • 按输出格式输出(分为纯整数、真分数、假分数和零)

    注意点

  • 相加过程中可能使分子或分母超过int型表示范围,有两种处理方法:

    1.直接用long long来存储。这种情况尤其体现在分数的乘法除法过程中;

    2.每次相加后就约分,避免分子分母过大。

  • 约分化简主要利用的是欧几里得算法求最大公约数。

    1
    2
    3
    4
    5
    int gcd(int a, int b)
    {
    if( b == 0) return a;
    else return gcd( b, a % b);
    }

    更简洁的写法:

    1
    2
    3
    4
    int Gcd(int a, int b)
    {
    return !b ? a : Gcd(b, a % b);
    }
  • 分数累加时,要通分,注意先改变分子,再改变分母(因为分子需要利用原来的分母构成)

题解代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<iostream>
using namespace std;

struct Fraction{
int fz;
int fm;
};//分数结构体

int Gcd(int a,int b){
if(b==0) return a;
return Gcd(b,a%b);
}//求最大公约数

Fraction yue(Fraction f){
//对分数进行化简
int y=Gcd(abs(f.fz),abs(f.fm));
f.fz/=y;
f.fm/=y;
return f;
}

int main(){
int n;
cin >> n;
Fraction res;//结果
res.fm=1;
res.fz=0;
while(n--){
int a,b;//输入数据的分子a 分母b
scanf("%d/%d",&a,&b);
res.fz=res.fz*b+res.fm*a;
res.fm*=b;
//先变分子,后变分母
res=yue(res);//约分
}
//输出分数结果
int zheng=0;
if(abs(res.fz) >= abs(res.fm)){
//有整数部分
zheng=res.fz/res.fm;
cout<<zheng;
res.fz=res.fz%res.fm;
if(res.fz!=0){
//有分数部分
cout<<" "<<res.fz<<"/"<<res.fm;
}
}else{
if(res.fz==0) cout<<"0";//0
else{
//只有分数部分
cout<<res.fz<<"/"<<res.fm;
}
}
return 0;
}