
Алгоритм вычисления значения функции F(n), где n — целое число, задан следующими соотношениями:
если
если
Определите количество
Решение. Приведём решение на языке Python.
from functools import *
# граничное значение
a = list(map(int, str(2**63-1)))
@lru_cache(None)
def f(s, l, fl):
# если последовательность нужной длины, проверяем, что сумма нам подходит,
# и выходим из рекурсии.
if l == 0: return s == 159
# проверяем ограниченные подпоследовательности большей длины
return sum(f(s+x, l-1, fl and (x == a[-l])) for x in range([10, a[-l]+1][fl]))
# ответ - количество ограниченных последовательностей необходимой длины
print(f(0, len(a), 1))
Ответ: 34602572.
Приведём вариант приведенного решения от Юрия Красильникова на языке Python с комментариями.
import functools
границы = list(map(int,str(2**63-1)))
# границы - это десятичные цифры числа 2**63-1. Мы не должны превышать это число.
@functools.lru_cache(None)
# Организуем кэш для того, чтобы избежать повторных перевычислений функции
def f(сумма, позиция, на_пределе):
# сумма - частичная сумма цифр числа
# позиция - позиция очередной цифры, которую мы перебираем
# на_пределе - это логическая переменная. Значение «истина» означает, что все предыдущие цифры -
# «на пределе» и поэтому текущая цифра тоже не должна превышать границу для неё.
# «Ложь» - слева есть цифры менее предельных и поэтому текущая цифра может быть любой
if позиция == len(границы): # мы достигли максимально возможной длины числа
return 1 if сумма == 159 else 0 # возвращаем 1, если получилась нужная сумма цифр
предел = (границы[позиция] if на_пределе else 9)+1
# если «на пределе» - перебираем цифры до границы, иначе - все цифры
return sum(f(сумма+цифра,позиция+1,на_пределе and цифра==границы[позиция]) for цифра in range(предел))
# суммируем результаты для всех возможных следующих цифр
print(f(0,0,True)) # начинаем с позиции 0, и первая (старшая) цифра не должна превышать границу
PDF-версии: