https://projecteuler.net/problem=26
Reciprocal cycles
Problem 26
A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857) 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1
Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
因为分母部分保持不变,所以只要分子部分一旦重复出现,循环小数的数量就确定下来了。而分子部分其实就是对分母取余剩下的那部分。 可以测试一下1/7即可。
因为取余的值不会大于分母,所以计算量也不会大于分母。
当然,有一个公式可以算出素数的循环小数的位数,用起来更简单一点,不过1000个也就没有必要了。
当然除了像下面这样蛮算,还可以将数拆分下来,求所有的因子,如:1/21 = 1/3 * 1/ 7他的循环小数位数 就是 1 * 6.依次类推,也挺简单的。
def ReciprocalCycles():
#循环小数数量集合
result = 0
maxNum = 0
for i in range(1,1000):
#找到每一个值的循环小数数量
tmp = CountCycle(i)
if maxNum < tmp:
maxNum = tmp
result = i
return result
def CountCycle(num):
#余数的字典,记录每一个余数所在的位置
ModDict={}
#把1初始化进去
ModDict[1]=0
#记录下一个余数所在位置
index=1
#下一个除数是1 * 10
Numerator = 10
#求取第一个真正的余数
modNum = Numerator % num
#如果余数为零,或者余数之前出现过,则退出,否则一直进行
while modNum != 0 and modNum not in ModDict:
#将余数和其位置放到字典里面
ModDict[modNum] = index
#除数初始化
Numerator = modNum * 10
#求余数
modNum = Numerator % num
#更新余数的下一个位置
index += 1
#如果能除尽,则不是循环小数
if modNum == 0:
return 0
#返回两个相同余数的位置差,就是循环小数的数量
return index - ModDict[modNum]
print(ReciprocalCycles())