92 lines
2.5 KiB
Python
92 lines
2.5 KiB
Python
"""
|
||
An irrational decimal fraction is created by concatenating the positive integers:
|
||
0.123456789101112131415161718192021...
|
||
|
||
It can be seen that the 12th digit of the fractional part is 1.
|
||
|
||
If d_n represents the nth digit of the fractional part, find the value of the following expression.
|
||
|
||
d_1 × d_10 × d_100 × d_1000 × d_10000 × d_100000 × d_1000000
|
||
"""
|
||
|
||
import time
|
||
|
||
def timer(func):
|
||
def wrapper(*args, **kwargs):
|
||
start_time = time.time()
|
||
result = func(*args, **kwargs)
|
||
end_time = time.time()
|
||
print(f"{func.__name__} time: {end_time - start_time:.6f} seconds")
|
||
return result
|
||
return wrapper
|
||
|
||
class ChampernownesConstant:
|
||
def __init__(self):
|
||
self._cache = "123456789"
|
||
self._level = 1
|
||
self._nth = 1
|
||
|
||
def __iter__(self):
|
||
if self._nth > len(self._cache):
|
||
self._level += 1
|
||
self._cache += "".join(str(i) for i in range(10**(self._level-1), 10**self._level))
|
||
yield self._cache[self._nth-1]
|
||
self._nth += 1
|
||
|
||
def __next__(self):
|
||
return next(self.__iter__())
|
||
|
||
def get_nth_digit(self, nth:int) -> int :
|
||
while True:
|
||
if nth > len(self._cache):
|
||
self._level += 1
|
||
self._cache += "".join(str(i) for i in range(10**(self._level-1), 10**self._level))
|
||
else:
|
||
return int(self._cache[nth-1])
|
||
|
||
|
||
@timer
|
||
def main_longstring() -> None:
|
||
gen = ChampernownesConstant()
|
||
ziel = [1,10,100,1000,10000,100000,1000000]
|
||
res = 1
|
||
for i in ziel:
|
||
res *= gen.get_nth_digit(i)
|
||
print(res)
|
||
|
||
|
||
def length_numbers(k:int) -> int :
|
||
"""计算前k位数的总位数"""
|
||
if k == 0:
|
||
return 0
|
||
return (10**k * (9*k - 1) + 1) // 9
|
||
|
||
|
||
def get_nth_digit(nth:int) -> int :
|
||
if nth < 0 :
|
||
raise ValueError("nth must be non-negative")
|
||
level = 1
|
||
while length_numbers(level) < nth :
|
||
level += 1
|
||
# 计算在k位数中的偏移量
|
||
offset = nth - length_numbers(level-1) # 在k位数中的第几个数字
|
||
num_index = (offset - 1) // level # 第几个k位数(从0开始)
|
||
num = 10**(level-1) + num_index # 具体的数字
|
||
digit_index = (offset - 1) % level # 在数字中的位置
|
||
|
||
return int(str(num)[digit_index])
|
||
|
||
|
||
@timer
|
||
def main_quick() -> None :
|
||
ziel = [1,10,100,1000,10000,100000,1000000]
|
||
res = 1
|
||
for i in ziel:
|
||
res *= get_nth_digit(i)
|
||
print(res)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main_longstring()
|
||
main_quick()
|