题193.2022寒假天梯赛训练-7-4 N个数求和 (20 分)
一、题目
二、题解
本题两个关键,通分与约分。需用到求最大公约数与最小公倍数的算法。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll up[101],down[101];
ll gcd(ll x,ll y)//Stein算法,说是效率最高的求两数最大公约数的算法
{
x=abs(x);y=abs(y);//这个算法没法算负数
ll i,j,t;
if (x == 0 ) return y;
if (y == 0 ) return x;
for (i = 0 ; 0 == (x & 1 ); x >>= 1, ++ i);
for (j = 0 ; 0 == (y & 1 ); y >>= 1, ++ j);
if (j < i) i = j;
for (;;)
{
if (x < y) t = y,y = x,x = t;
if ( 0 == (x -= y)) return y << i;
for (; 0 == (x & 1); x >>= 1 );
}
}
/*
ll gcd(ll a, ll b){ //欧几里得算法(辗转相除)求a,b最大公约数
if(b) return gcd(b, a%b);
return a;
}
*/
ll lcm(ll x,ll y)
{
return x*y/gcd(x,y);
}
int main()
{
int N;
cin>>N;
//downlcm,upsum分别表示当前循环下的分子总和与分母的最大公约数。进入循环后不断往最终的分母最大公约数,分子总和发展
ll downlcm=1,upsum=0;//当时这里写了个int,然后我就被困了一个多小时,我真的服了我自己了
for(int i=0;i<N;i++)//采用一边输入新的分数,一边计算分数和
{
scanf("%lld/%lld",&up[i],&down[i]);
ll downtmp=downlcm;//还有这里
downlcm=lcm(down[i],downlcm);
upsum=upsum*(downlcm/downtmp)+up[i]*(downlcm/down[i]);//通分相加
}
ll resgcd=gcd(upsum,downlcm);//求出最后结果分数的分子分母最大公约数用于约分
//约分
ll res_up=upsum/resgcd;
ll res_down=downlcm/resgcd;
ll integer=res_up/res_down;
res_up=res_up%res_down;
if(integer==0&&res_up!=0)//整数为0且分子不为0则只输出分数部分
{
printf("%lld/%lld",res_up,res_down);
}
else if(res_up==0)//整数不为0且分子为0则只输出整数部分
{
printf("%lld",integer);
}
else
{
printf("%lld %lld/%lld",integer,res_up,res_down);
}
}
/*
5
-1/2 -1/2 -1/2 -1/2 -1/2
-2 -1/2(貌似1/-2也行)
*/