1062 最简分数 (20 分)

1062 最简分数 (20 分)

题意描述:

一个分数一般写成两个整数相除的形式:N / M,其中 M 不为0。最简分数是指分子和分母没有公约数的分数表示形式。

现给定两个不相等的正分数 N​1​​ / M​1​​ 和 N​2​​ / M​2​​ ,要求你按从小到大的顺序列出它们之间分母为 K 的最简分数。

输入格式:
输入在一行中按 N / M 的格式给出两个正分数,随后是一个正整数分母 K,其间以空格分隔。题目保证给出的所有整数都不超过 1000。

输出格式:
在一行中按 N / M 的格式列出两个给定分数之间分母为 K 的所有最简分数,按从小到大的顺序,其间以 1 个空格分隔。行首尾不得有多余空格。题目保证至少有 1 个输出。

输入样例:

7/18 13/20 12

输出样例:

5/12 7/12

解题思路:
Mara: 这些分数的题目做来做去就是一堆整数加减乘除,有劲吗?
Jack: 有劲啊,我最喜欢整数了,可以用指头感受的才是真实的。
Mara: 少废话了,这题怎么做啊 ?难道从 1 / K(K - 1) / K 一个一个的变成小数去比大小,这靠谱吗?
Jack: 题目里面有两个条件啊, 一是要大小位于两个分数之间,二是要求是最简分数。最简分数什么意思,分子和分母不能再约分,不能约分什么意思,没有TM的公约数了,没有公约数了什么意思,TM的最大公约数是1 啊。怎么求两个数的最大公约数啊,TM的欧几里得辗转相除啊。还有你想和小数TM的比大小,那能比的准吗?分数是什么,分数乘以分母就都是整数,通分呐,通分完了之后用整数比大小不就的了吗。把问题转化成你熟悉的模式,对,基本就是这样。
Mara: 你TM的敢吼我,我问你,两个分数之间到底是开区间还是闭区间。
Jack: 我怎么知道,题目里面又TM没说,写个程序试呗。
Mara: 我就知道!
Jack: 你知道什么,试出来了,是开区间。
Mara: ╭(╯^╰)╮ ╭(╯^╰)╮ ╭(╯^╰)╮ ╭(╯^╰)╮
Jack: (ノ"◑ ◑)ノ"(。•́︿•̀。)(ノ"◑ ◑)ノ"(。•́︿•̀。)(ノ"◑ ◑)ノ"(。•́︿•̀。)(ノ"◑ ◑)ノ"(。•́︿•̀。)


代码:

def main():
    temp = [x for x in input().split()]
    # 以字符串列表的形式接收输入的两个分数和一个整数,形如['7/18', '13/20', '12']
    N1, M1 = (int(x) for x in temp[0].split('/'))
    N2, M2 = (int(x) for x in temp[1].split('/'))
    # 分别获取两个分数的分子和分母
    K = int(temp[2])
    # 分母 K
    # 将N1/M1, N2/M2, X/K通分,通分后仍满足 X/K 位于两个分数之间。此时分母相
    # 同,只需要确定分子的上下界就可以找到所有在这个范围内的分数。 
    minn = min(N1 * M2 * K, N2 * M1 * K)
    maxx = max(N1 * M2 * K, N2 * M1 * K)
    # 由于题目中没有给出N1/M1 N2/M2之间的大小关系,所以我们需要自己确定最小值和最大值
    answer = []
    #print(minn, maxx)
    for x in range(1, K):
        # 可能的答案有1/K ...... K-1 / k, 来,让我们遍历这个序列
        if between(minn, maxx, x * M1 * M2) and gcd(K, x) == 1:
            # 如果这个分数在给定的范围内,而且分子和分母的最大公约数是1,即是满
            # 足条件的最简分数。
            # x * M1 * M2 是通分之后的结果。注意我们这里先判断了这个分数是否在
            # 给定的范围内,如果是的话,由于 and 的短路原则就不必再计算 最大公约
            # 数,这样就能减少一些计算。
            answer.append('{}/{}'.format(x, K))
        else:
            #print("gcd {} {}".format(K, x), gcd(K, x), )
            pass
    print(" ".join(answer))
    # 使用join方法将字符串拼接起来并输出答案


def gcd(a, b):
    # 辗转相除法求两个非负整数的最大公约数
    if b == 0:
        return a
    else:
        return gcd(b, a % b)


def between(minn, maxx, x):
    # 判断 x 是否在(minn, maxx)这个区间内
    if x > minn and x < maxx:
        return True
    else:
        return False

if __name__ == '__main__':
    main()


易错点:

  • 经测试得,题目中两个分数之间是指开区间而非闭区间。
  • 如果用浮点数去存储分数,要考虑浮点误差带来的影响。

总结:

  • 二进制喜欢整数,我也是。有时候我们解决的问题并不是问题直接呈现的样子,题目描述往往只是表面的展示,解题的每种方式都是看待这个问题的一种角度。同样的,平凡的每一天都可以用不同的角度去打量。人们往往没有他们所想的那样幸福或者不幸,我们只是用夸张来掩盖平凡庸俗的事实罢了。所以,请放肆一点,嚣张一点,勇敢一点,毕竟我们只活一次。

悲天悯人


  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值