Проект Эйлер-Задача 160
для любого N пусть f (N) - последние пять цифры перед конечными нулями Н!. Например,
9! = 362880 so f(9)=36288 10! = 3628800 so f(10)=36288 20! = 2432902008176640000 so f(20)=17664
найти f (1,000,000,000,000)
Я успешно решил этот вопрос для приведенных примеров, моя функция может правильно найти f(9), f (10) и т. д. Однако он борется с большими числами, особенно с числом, которое требует проблема-f (10^12).
мои текущие оптимизации следующие: я удаляю конечные нули из множитель и сумма, и сократить сумму до 5 знаков после каждого умножения. Код в python выглядит следующим образом:
def SFTR (n):
sum, a = 1, 2
while a < n+1:
mul = int(re.sub("0+$","",str(a)))
sum *= mul
sum = int(re.sub("0+$","",str(sum))[-5:])
a += 1
return sum
может ли кто-нибудь сказать мне, почему эта функция масштабируется так широко, и почему это занимает так много времени. Также, если кто-нибудь может намекнуть мне в правильном направлении, чтобы оптимизировать мой алгоритм. (название общей темы будет достаточно) Спасибо.
обновление:
я внес некоторые изменения для оптимизации, и это значительно быстрее, но все равно недостаточно быстро для f(10^12). Может ли кто-нибудь сказать мне, что делает мой код медленным или как сделать его быстрее?
def SFTR (n):
sum, a = 1, 2
while a < n+1:
mul = a
while(mul % 10 == 0): mul = mul/10
mul = mul % 100000
sum *= mul
while(sum % 10 == 0): sum = sum/10
sum = sum % 100000
a += 1
return sum
3 ответов
mul
может стать очень большим. Это необходимо? Если бы я попросил вас вычислить последние 5 ненулевых цифр 1278348572934847283948561278387487189900038 * 38758
вручную, сколько именно цифр первого числа вам действительно нужно знать?
построение строк часто дорого. Я бы предпочел использовать оператор по модулю при усечении до последних пяти цифр.
python -m timeit 'x = str(111111111111111111111111111111111)[-5:]'
1000000 loops, best of 3: 1.09 usec per loop
python -m timeit 'x = 111111111111111111111111111111111 % 100000'
1000000 loops, best of 3: 0.277 usec per loop
то же самое относится к зачистке конечных нулей. Должен быть более эффективный способ сделать это, и вам, вероятно, не нужно делать это на каждом шагу.
Я не проверял ваш алгоритм на правильность, хотя это всего лишь подсказка для оптимизации.
фактически, вы можете даже отметить, что существует только ограниченный набор возможных конечных ненулевых цифр. Если я правильно помню, есть только несколько тысяч возможных комбинаций с ненулевыми цифрами, когда вы смотрите только на последние 5 цифр. Например, возможно ли, чтобы конечная ненулевая цифра когда-либо была нечетной? (Игнорируйте особые случаи 0! и 1! здесь.)