题目
题目描述
蒜头君有 n 个分数并想对他们求和,并用最简形式表示。所谓最简形式是指:分子分母的最大公约数为 1;若最终结果的分母为 1,则直接用整数表示。
如:5/6、10/3 均是最简形式,而 3/6 需要化简为 1/2, 3/1 需要化简为 3。
分子和分母均不为 0,也不为负数。
输入格式
第一行是一个整数 n,表示分数个数,1 ≤ n ≤ 10;
接下来 n 行,每行一个分数,用 “p/q” 的形式表示,不含空格,p,q 均不超过 1010。
输出格式
输出只有一行,即最终结果的最简形式。若为分数,用 “p/q” 的形式表示。
样例输入
2
1/2
1/3
样例输出
5/6
解题
思路分析
- 分数求和之前,若分母不同,则需要进行通分
- 通分需要得到两个分母的最小公倍数
- 然后以最小公倍数分别除以分母得到系数
- 各自系数乘以分子相加后得到求和后的分子;分母即为最小公倍数
- 分数求和之后,需要约分成最简形式
- 约分需要知道两个分母的最大公约数
- 如果分子可以整除分母,则通过整除约分得到整数形式。
- 因此得到需求条件:
- 最大公约数(利用辗转相除法)
- 最小公倍数(两数之积除以两数最大公约数)
代码实现
辗转相除法求最大公约数
def zzxc(m, n):
max_v = max(m, n)
min_v = min(m, n)
r = max_v % min_v
while r != 0:
max_v = min_v
min_v = r
r = max_v % min_v
return min_v
分数相加
def fenshu(m, n):
m_fz, m_fm = map(int, m.split('/'))
n_fz, n_fm = map(int, n.split('/'))
max_gb = zzxc(m_fm, n_fm)
min_gy = m_fm * n_fm // max_gb
m_xs = min_gy // m_fm
n_xs = min_gy // n_fm
new_fz = m_fz * m_xs + n_fz * n_xs
yf_xs = zzxc(new_fz, min_gy)
new_fz //= yf_xs
min_gy //= yf_xs
return str(new_fz) + '/' + str(min_gy)
根据题意进行运算
n = int(input())
ls = []
for i in range(0, n):
ls.append(input())
for i in range(0, n - 1):
ls[0] = fenshu(ls[0], ls[1])
del ls[1]
fz, fm = map(int, ls[0].split('/'))
if fz % fm == 0:
print(fz // fm)
else:
print(str(fz) + '/' + str(fm))
完整代码
def zzxc(m, n):
max_v = max(m, n)
min_v = min(m, n)
r = max_v % min_v
while r != 0:
max_v = min_v
min_v = r
r = max_v % min_v
return min_v
def fenshu(m, n):
m_fz, m_fm = map(int, m.split('/'))
n_fz, n_fm = map(int, n.split('/'))
max_gb = zzxc(m_fm, n_fm)
min_gy = m_fm * n_fm // max_gb
m_xs = min_gy // m_fm
n_xs = min_gy // n_fm
new_fz = m_fz * m_xs + n_fz * n_xs
yf_xs = zzxc(new_fz, min_gy)
new_fz //= yf_xs
min_gy //= yf_xs
return str(new_fz) + '/' + str(min_gy)
n = int(input())
ls = []
for i in range(0, n):
ls.append(input())
for i in range(0, n - 1):
ls[0] = fenshu(ls[0], ls[1])
del ls[1]
fz, fm = map(int, ls[0].split('/'))
if fz % fm == 0:
print(fz // fm)
else:
print(str(fz) + '/' + str(fm))