题目:
本题的要求很简单,就是求
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
最初始的思路(极其笨吧)
首先利用vector<string> 放入每一个读入的字符串,再依次进行处理,以/作为分界线,分情况讨论。/左边我们从左到右存到分子数组里面,/右边我们从右往左处理数字,得到分母,放进分母数组,也就是说,我们用vector<string>维护了一个二维数组,用分子数组维护了所有分子,用分母维护了所有分母。害,太笨了,最后也才11分啊!!!!!!!!我居然想一次性通分所有的分母,再一次性处理所有的分子。就没有考虑到长整型!!!范围内。
11分代码如下所示:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N = 110;
LL fm[N],fz[N];
LL gcd(LL m,LL n)
{
while(n!=0)
{
LL temp = m%n;
m = n;
n = temp;
}
return m;
}
int main()
{
int n;
scanf("%d",&n);
vector<string> v;
for(int i = 0;i<n;i++)
{
string s;
cin>>s;
v.push_back(s);
}
LL k = 0,h = 0;
// for(auto e:v)
// cout<<e<<endl;
for(auto e:v)
{
int sum = 0,num;// 开始处理分母
for(int i = e.size()-1,j = 0;e[i]!='/';i--)
{
num = 1;
num*=pow(10,j);
num*=e[i]-'0';
sum+=num;
j++;
}
fm[k++] = sum;// 预处理完分母
}
for(auto c:v)
{
int num = 0;
if(c[0]=='-')
{
for(int i = 1;c[i]!='/';i++)
{
num*=10;
num+=c[i]-'0';
}
fz[h++] = -1*num;
}
else if(c[0]!='-')
{
for(int i = 0;c[i]!='/';i++)
{
num*=10;
num+=c[i]-'0';
}
fz[h++] = num;
}
}
// cout<<k<<h<<endl;
LL ca = 1;
for(int i = 0;i<k;i++)
{
ca*=fm[i];
}
LL ba = 0;
for(int i = 0;i<h;i++)
{
long long t = ca/fm[i];
fz[i]*=t;
ba+=fz[i];
}
LL zx = gcd(ca,ba);
LL zz = ba%ca;
if(ba==0&&zz==0)
cout<<0<<endl;
if(ba<ca)
cout<<ba/zx<<'/'<<ca/zx;
else
{
cout<<ba/ca<<" "<<zz/gcd(ca,zz)<<'/'<<ca/gcd(ca,zz);
}
return 0;
}
20分思路:
首先,应该没有开辟数组,一开始先让fz1 = 0,fm1 = 1。再开一个zs,作为存取整数部分。fz2和fm2一个一个的处理读入的数据。维护整数部分,剩余的分数部分赋值给fz1和fm2,这样我们每次都是来一个计算一个,如果有整数溢出,那我们就加到zs里面。一次性只通分处理两个。我代码格式写的好丑,但便于理解我全部用拼音了。不过能过,如果有简单处理这题的代码,一定记得发给我哦。(最后我们看情况输出zs和fz1以及fm1就行)。
20分代码如下:
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
long long gcd(long long n,long long m)
{
while(m)
{
int t = n%m;
n = m;
m = t;
}
return n;
}
int main()
{
int n;
scanf("%d",&n);
long long zs = 0,fz1 = 0,fm1 = 1;
for(int i = 0;i<n;i++)
{
string s;
cin>>s;
long long fz2 = 0,fm2 = 0;
// 预处理分母
for(int i = s.size()-1,j = 0;s[i]!='/';i--)
{
int num = 1;
num*=pow(10,j);
num*=(s[i]-'0');
fm2 += num;
j++;
}
// 预处理分子
bool flag = false;//是否为负数
long long num1;
for(int i = 0;s[i]!='/';i++)
{
if(s[i]=='-')
{
flag = true;
continue;
}
fz2*=10;
fz2+=s[i]-'0';
}
if(flag) // 若是负数,应该乘以负一
fz2 = -1*fz2;
long long tongfen = fm1*fm2; // 求两个分母的公约数,先通分
fz1 = fz1*tongfen/fm1;
fz2 = fz2*tongfen/fm2;
long long leijia = fz1+fz2; //分子相加
//看看相加后整数得绝对值是否比分母大,
zs += leijia/tongfen;//处理整数部分
long long fenzi = leijia%tongfen;// 存取分数部分的分子
long long zuida = gcd(tongfen,fenzi); // 求最大公约数
fz1 = fenzi/zuida;// 当然还需要化成最简形式
fm1 = tongfen/zuida; // 分母也要除以最大公约数
}
if(zs&&fz1!=0)
cout<<zs<<" "<<fz1<<'/'<<fm1<<endl;
else if(zs==0&&fz1!=0)
cout<<fz1<<'/'<<fm1<<endl;
else if(zs&&fz1==0)
cout<<zs<<endl;
else if(zs==0&&fz1==0)
cout<<0<<endl;
return 0;
}
欢迎和我一起讨论进步!!!