1081. Rational Sum (20) -最大公约数

题目如下:

Given N rational numbers in the form "numerator/denominator", you are supposed to calculate their sum.

Input Specification:

Each input file contains one test case. Each case starts with a positive integer N (<=100), followed in the next line N rational numbers "a1/b1 a2/b2 ..." where all the numerators and denominators are in the range of "long int". If there is a negative number, then the sign must appear in front of the numerator.

Output Specification:

For each test case, output the sum in the simplest form "integer numerator/denominator" where "integer" is the integer part of the sum, "numerator" < "denominator", and the numerator and the denominator have no common factor. You must output only the fractional part if the integer part is 0.

Sample Input 1:
5
2/5 4/15 1/30 -2/60 8/3
Sample Output 1:
3 1/3
Sample Input 2:
2
4/3 2/3
Sample Output 2:
2
Sample Input 3:
3
1/3 -1/6 1/8
Sample Output 3:
7/24



题目要求对分数进行处理,题目的关键在于求取最大公约数,最初我采用了循环出现超时,后来改用辗转相除法,解决了此问题。需要注意的是分子为负数的情况,为方便处理,我们把负数取绝对值,并且记录下符号,最后再输出。

辗转相除法如下:

给定数a、b,要求他们的最大公约数,用任意一个除以另一个,得到余数c,如果c=0,则说明除尽,除数就是最大公约数;如果c≠0,则用除数再去除以余数,如此循环下去,直至c=0,则除数就是最大公约数,直接说比较抽象,下面用例子说明。

设a=25,b=10,c为余数

①25/10,c=5≠0,令a=10,b=5。

②10/5,c=0,则b=5就是最大公约数。

求取最大公约数的代码如下:

long getMaxCommon(long a, long b){
    long yu;
    if(a == b) return a;
    while(1){
        yu = a % b;
        if(yu == 0) return b;
        a = b;
        b = yu;
    }
}

完整代码如下:

#include <iostream>
#include <stdio.h>
#include <vector>

using namespace std;

struct Ration{
    long num;
    long den;

    Ration(long _n, long _d){
        num = _n;
        den = _d;
    }

};

long getMaxCommon(long a, long b){
    long yu;
    if(a == b) return a;
    while(1){
        yu = a % b;
        if(yu == 0) return b;
        a = b;
        b = yu;
    }
}

int main(){
    int N;
    long num,den;
    long maxDen = -1;
    cin >> N;
    vector<Ration> rations;
    for(int i = 0; i < N; i++){
        scanf("%ld/%ld",&num,&den);
        rations.push_back(Ration(num,den));
        if(maxDen == -1){
            maxDen = den;
        }else{
            // 找maxDen和当前的最小公倍数
            if(den == maxDen) continue;
            else if(maxDen > den){
                if(maxDen % den == 0) continue;
            }else{
                if(den % maxDen == 0){
                    maxDen = den;
                    continue;
                }
            }
            maxDen = maxDen * den;
        }
    }
    num = 0;
    for(int i = 0; i < N; i++){
        num += rations[i].num * (maxDen / rations[i].den);
    }
    if(num == 0) {
        printf("0\n");
        return 0;
    }
    bool negative = num < 0;
    if(negative) num = -num;
    if(num >= maxDen){
        long integer = num / maxDen;
        long numerator = num % maxDen;
        if(numerator == 0){
            if(negative)
                printf("-%ld\n",integer);
            else
                printf("%ld\n",integer);
            return 0;
        }
        long common = getMaxCommon(numerator,maxDen);
        if(negative){
            printf("%ld -%ld/%ld\n",integer,numerator/common,maxDen / common);
        }else{
            printf("%ld %ld/%ld\n",integer,numerator/common,maxDen / common);
        }
    }else{
        long common = getMaxCommon(num,maxDen);
        if(negative)
            printf("-%ld/%ld\n",num/common,maxDen/common);
        else
            printf("%ld/%ld\n",num/common,maxDen/common);
    }
    return 0;
}


转载于:https://www.cnblogs.com/aiwz/p/6154051.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值