分享一道平时写的题
本题的要求很简单,就是求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
测试点3是测试的长整型,关键点:看函数返回类型是否也是长整型
测试点5的测试是所有分子加起来后刚好等于0,直接输出0就行
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
long long gcd(long long a, long long b)//辗转相除法
{
while (b)
{
long long tmp = a % b;
a = b;
b = tmp;
}
return a;
}
int main()
{
int n = 0;
scanf("%d", &n);
long long* arr1 = (long long*)calloc(n, sizeof(long long));//存分子
long long* arr2 = (long long*)calloc(n, sizeof(long long));//存分母
int i = 0;
long long tmp = 0;//原本准备创建一个临时变量,后来当成分母用了
for (i = 0; i < n; i++)
{
scanf("%lld/%lld", arr1 + i, arr2 + i);
if(arr1[i]==0)
{
n--;
i--;
continue;
}
if (!i)//当i=0时,不需要算最小公倍数
{
tmp = arr2[0];
}
else
{
long long gcd1 = gcd(arr2[i], tmp);
tmp = (arr2[i] * tmp) / gcd1;//这里算 所有分母的最小公倍数=两数相乘/最大公约数
}
}
long long sum = 0;//sum是分子
while (n > 0)
{
sum += tmp / arr2[n - 1] * arr1[n - 1];//所有分子通分后加起来
n--;
}
if(sum==0)//如果分子为零(测试点5)
{
printf("0");
return 0;
}
long long gc = gcd(sum%tmp, tmp);
if (sum / tmp==0)
{
printf("%lld/%lld\n", sum/ gc, tmp / gc);
}
else if (sum%tmp==0)
{
printf("%lld\n", sum / tmp);
}
else
{
printf("%lld %lld/%lld\n", sum / tmp, sum % tmp / gc, tmp / gc);
}
free(arr1);
free(arr2);
arr1=NULL;
arr2=NULL;
return 0;
}