试题 历届真题 循环小数【第十一届】【决赛】【Python】

一、题目来源:第十一届蓝桥杯决赛——循环小数

资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

【问题描述】
已知S是一个小于1的循环小数,请计算与S相等的最简真分数是多少。
例如 0.333··· 等于 1 3 1\over{3} 31 , 0.1666··· 等于 1 6 1\over 6 61

【输入格式】
输入第一行包括两个整数 p p p q q q ,表示 S S S 的循环节是小数点后第 p p p 位到第 q q q 位。
第二行包含一个 q q q 位数,代表 S S S 的小数部位前 q q q 位。

【输出格式】
输出两个整数,用一个空格隔开,分别表示答案的分子和分母。

【样例输入】
1 6
142857
【样例输出】
1 7

二、解题

1、循环小数

循环小数(circulating decimal),是指一个数的小数部分从某一位起,一个或几个数字依次重复出现的无限小数。
循环小数会有循环节(循环点),并且可以化为分数。

2、循环小数转分数

纯循环小数
将纯循环小数改写成分数,分子是一个循环节的数字组成的数;分母各位数字都是9,9的个数与循环节中的数字的个数相同.
例如:0.111…=1/9、0.12341234…=1234/9999

混循环
将混循环小数改写成分数,分子是不循环部分与第一个循环节连成的数字组成的数,减去不循环部分数字组成的数之差;分母的头几位数字是9,末几位数字是0,9的个数跟循环节的数位相同,0的个数跟不循环部分的数位相同.
例如:0.1234234234…=(1234-1)/9990 0.55889888988898…=(558898-55)/999900

3、代码

import fractions

p,q = map(int,input().split()) # 第p位到第q位是循环节
num = input() # 小数部分(小数点后一位到第一个循环节最后一位)
repeat_len = q-p+1 # 循环节的位数
num_len = len(num) # 小数部分的长度 = 非循环部分长度+一个循环节长度(repeat_len)
num = int(num) # input()输入的数据,默认以str类型接收
numerator,denominator=1,1 # 分子,分母

if repeat_len == num_len: # 纯循环小数(循环从第1位开始)
    # 分子是一个循环节的数字组成的数
    numerator = num 
    # 分母各位数字都是9,9的个数与循环节中的数字的个数相同
    denominator = 10**num_len-1 
else: # 混循环小数
    # 分子是非循环部分与第一个循环节连成的数字组成的数,减去非循环部分数字组成的数之差
    numerator = num - num // (10**(repeat_len)) 
    # 分母的头几位数字是9,末几位数字是0,9的个数跟循环节的数位相同,0的个数跟不循环部分的数位相同.
    denominator = (10**repeat_len-1) * (10**(p-1)) 

# Fraction(arg1,arg2)可以将将arg1/arg2化简为最简分数的形式
print(*str(fractions.Fraction(numerator,denominator)).split('/')) # split('/')是根据字符串中的'/'将字符串分隔开
# *:解包,将list中的元素按元素输出,输出就不会带 "[" , "]"和","

三、总结

1、最关键是知道循环小数转分数的规则。如果不知道这个规则,基本解不出来。
2、使用fractions里的Fraction()将分数为最简分数形式。当然可以用辗转相除法,但使用python应该学会使用一些包(蓝桥杯可以使用的,笔者在蓝桥杯练习系统中可以使用),不然用python的优势就体现不出。

你可能感兴趣的:(蓝桥杯,python,蓝桥杯,循环小数转分数规则)