正文索引 [隐藏]

在pta上完成数据结构的课程作业时发现一道很有意思的题,记录一下。传送门

题面

本题要求编写程序,计算N个有理数的平均值。

输入

输入第一行给出正整数N(≤100);第二行中按a1/b1,a2/b2…的格式给出N个分数形式的有理数,其中分子和分母全是整形范围内的整数;如果是负数,则负号一定出现在最前面。

输出

在一行中按a/b的格式输出N个有理数的平均值。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。

样例

样例输入1
4
1/2 1/6 3/6 -5/10
样例输出1
1/6
样例输入2
2 
4/3 2/3 
样例输出2
1

这题成功的让我拓宽了关于c语法的知识面,所以我在此记录下来,虽然它不算经典意义上的难题与要题。

首先,因为题目中指明是有理数,所以可以求最小公约数来约分计算,难度降低了不少。使用C++的pair类来存储分子与分母,然后分别读入它们再累加求平均数即可。

#include <cmath>
#include <cstdio>
#include <utility>
#include <cstring>
#include <iostream>
#include <algorithm>

#define get(x) scanf("%d", &x)
#define lget(x) scanf("%lld", &x)
#define set(a,b) memset(a, b, sizeof(a))
#define rep(a, b, c) for (int a = b; a <= c; a++)

using namespace std;

const int INF = 0X7F7F7F7F;

int n;

int gcd(int a, int b)
{
    return !b ? a : gcd(b, a%b);
}

int main()
{
    cin >> n;
    pair<int, int> p;
    pair<int, int> ans;
    scanf("%d/%d",&p.first, &p.second);
    for (int i = 1; i < n; i++)
    {
        scanf("%d/%d", &ans.first, &ans.second);
        p.first =  p.first*ans.second + p.second*ans.first;
        p.second = p.second*ans.second;

    }//如果分子不能整除n就让分母乘以n
    if (p.first%n == 0) p.first /= n;
    else p.second *= n;
    if (p.first == 0)
    {//如果分子是0那就直接输出并结束程序
        cout << 0;
        return 0;
    } //计算最大公约数
    int mgcd = gcd(p.first, p.second);
    //约分
    p.first /= mgcd;
    p.second /= mgcd;
    if(p.second == 1)//分母为1
        cout << p.first;
    else//分母不为1
        cout << p.first << "/" << p.second;
    return 0;
}

学习到了通过语句

scanf("%d/%d",&p.first, &p.second);

来分别读入整数的方式,感觉很新奇有趣,原来除了printf外scanf也可以分开处理。