L1-009 N个数求和 (20 分)
本题的要求很简单,就是求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
【思路】
本题我将分数类型写成一个结构体,这是基本的第一步。输入的时候其实可以直接用这种格式限定符"%d/%d"读取中间带有/的数据,我依稀记得有。这题我没用scanf,就只能写了一个toInteger函数将读入的字符串一步一步转换成整数。这就较麻烦了。
主要的算法操作就在add函数中了。这里第一次写完水过15分的测试点,但最后两个测试点硬是过不了。仔细思考之后,发现少考虑了情况。
一个是,-5 / 1或者5 / 1这种情况。一个是0 / 1这种情况,前一个输出-5或5即可,后一个输出0即可。改掉之后就没毛病了。
AC代码:
#include<iostream>
using namespace std;
#define ll long long
const int maxn = 105;
int n;
struct Fraction{
ll fz; //分子
ll fm; //分母
};
Fraction a[maxn];
void toInteger(string s, ll &fz, ll &fm)
{
int status = 0;
ll index = 0, i = 0, sum = 0; //表示分数中的斜线
for(i = 0;s[i] != '/';i++){
if(s[i] == '-'){
status = -1;
continue;
}
sum = sum * 10 + s[i] - '0';
}
index = i; //记录下此时的斜线下标
status == -1 ? fz = -sum : fz = sum;
status = 0;
sum = 0;
for(i = index + 1;i < s.size();i++){
if(s[i] == '-'){
status = -1;
continue;
}
sum = sum * 10 + s[i] - '0';
}
status == -1 ? fm = -sum : fm = sum;
}
ll gcd(ll a, ll b)
{
if(b == 0) return a;
else return gcd(b, a % b);
}
void add()
{
ll fz = a[1].fz, fm = a[1].fm;
ll g = gcd(fz, fm);
fz /= g; fm /= g;
//求分子分母分别的和
for(ll i = 2;i <= n;i++){
fz = fz*a[i].fm + fm*a[i].fz;
fm *= a[i].fm;
g = gcd(fz, fm);
fz /= g;
fm /= g;
}
//再求一次最大公约即可
if(fz == fm){cout << 1 << endl;}
else if(fz == -fm){cout << -1 << endl;} //又是一个大坑点!
else{
//-5 / 1这种情况,坑点!
ll shang = fz / fm;
if(shang != 0)
cout << shang;
fz -= fm * shang;
if(shang != 0 && fz != 0)
cout << " ";
if(fz != 0)
{
if(fm < 0)
cout << "-" << fz << "/" << -fm << endl;
else
cout << fz << "/" << fm << endl;
}
else if(fz == 0 && shang == 0)
cout << 0 << endl;
else if(fz == 0 && shang != 0)
cout << endl;
}
}
int main()
{
cin >> n;
string str;
ll fz, fm;
for(ll i = 1;i <= n;i++)
{
cin >> str;
toInteger(str, fz, fm);
//直接在输入的时候解决公约数问题
ll g = gcd(fz, fm);
a[i].fz = fz / g;
a[i].fm = fm / g;
//cout << fz << endl << fm << endl;
}
add();
return 0;
}