Допустим, у нас есть неотрицательное целое число, которое является «здоровенным» (то есть «тяжелым»), если его среднее значение цифры больше 7.
Число 6959 "здоровенное", потому что:
(6 + 9 + 5 + 9) / 4 = 7,5
Число 1234 нет, потому что:
(1 + 2 + 3 + 4) / 4 = 2,5
Написать функцию на любом языке,
HeftyDecimalCount(a, b)
который, при наличии двух положительных целых чисел a и b, возвращает целое число, указывающее, сколько «здоровенных» целых чисел находится в интервале [a..b] включительно.
Например, учитывая а = 9480 и б = 9489:
9480 (9+4+8+0)/4 21/4 = 5.25
9481 (9+4+8+1)/4 22/4 = 5.5
9482 (9+4+8+2)/4 23/4 = 5.75
9483 (9+4+8+3)/4 24/4 = 6
9484 (9+4+8+4)/4 25/4 = 6.25
9485 (9+4+8+5)/4 26/4 = 6.5
9486 (9+4+8+6)/4 27/4 = 6.75
9487 (9+4+8+7)/4 28/4 = 7
9488 (9+4+8+8)/4 29/4 = 7.25 hefty
9489 (9+4+8+9)/4 30/4 = 7.5 hefty
Два числа в этом диапазоне являются «здоровенными», поэтому функция должна возвращать 2.
Некоторые рекомендации:
- предположим, что ни a, ни b не превышают 200 000 000.
- n-квадратное решение будет работать, но будет медленным - что мы можем решить быстрее всего?
Ответы:
Проблема может быть решена в O (polylog (b)).
Мы определяем
f(d, n)
число целых чисел до d десятичных цифр с суммой цифр, меньшей или равной n. Видно, что эта функция задается формулойИспользуя эту формулу, мы можем, например, найти число тяжелых чисел в интервале от 8000 до 8999, поскольку
1000 - f(3, 20)
, поскольку в этом интервале есть тысячи чисел, мы должны вычесть число чисел с суммой цифр, меньшей или равной 28 принимая во внимание, что первая цифра уже вносит 8 в сумму цифр.В качестве более сложного примера давайте посмотрим на число тяжелых чисел в интервале 1234..5678. Сначала мы можем перейти с 1234 до 1240 с шагом 1. Затем мы с 1240 до 1300 с шагом 10. Приведенная выше формула дает нам число тяжелых чисел в каждом таком интервале:
Теперь мы идем от 1300 до 2000 с шагом 100:
От 2000 до 5000 с шагом 1000:
Теперь нам нужно снова уменьшить размер шага: с 5000 до 5600 с шагом 100, с 5600 до 5670 с шагом 10 и, наконец, с 5670 до 5678 с шагом 1.
Пример реализации Python (который получил небольшую оптимизацию и тестирование):
Редактировать : заменен код на оптимизированную версию (которая выглядит даже хуже, чем исходный код). Также исправил несколько угловых случаев, пока я был на нем.
heavy(1234, 100000000)
занимает около миллисекунды на моей машине.источник
binomial()
функция. Есть также еще несколько вещей, которые можно легко улучшить. Я выложу обновление через несколько минут.f(d, n)
не вызывается дважды с одинаковыми параметрами во время одного запуска программы.Рекурсировать и использовать перестановки.
Предположим, мы определили общую функцию, которая находит значения между a и b с большей тяжестью, чем x:
В вашем примере от a = 8675 до b = 8689, первая цифра 8, поэтому отбросьте ее - ответ будет таким же, как 675 до 689, и снова от 75 до 89.
Средний вес первых двух цифр 86 равен 7, поэтому для оценки оставшихся цифр требуется средний вес более 7. Таким образом, вызов
эквивалентно
Таким образом, наш диапазон для (новой) первой цифры составляет от 7 до 8, с этими возможностями:
Для 7 нам все еще нужно в среднем более 7, что может быть получено только из последней цифры 8 или 9, что дает нам 2 возможных значения.
Для 8 нам нужно в среднем более 6, что может быть получено только из последней цифры 7-9, что дает нам 3 возможных значения.
Таким образом, 2 + 3 дает 5 возможных значений.
Происходит то, что алгоритм начинается с 4-значного числа и делит его на более мелкие задачи. Функция будет вызывать себя неоднократно с более легкими версиями проблемы, пока у нее не будет чего-то, что она может обработать.
источник
Возможно, вы можете пропустить много кандидатов в интервале от a до b, накапливая их «тяжесть».
если вы знаете длину своего номера, вы знаете, что каждая цифра может изменить вес только на 1 / длину.
Итак, если вы начнете с одного не тяжелого числа, вы сможете рассчитать следующее число, которое будет тяжелым, если вы увеличите их на единицу.
В приведенном выше примере, начиная с 8680 ср = 5,5, что составляет 7-5,5 = 1,5 балла от границы тяжести, вы знаете, что между ними находится 1,5 / (1/4) = 6 чисел, которые НЕ являются тяжелыми.
Это должно в фокусе!
источник
/length
с.Как насчет простой рекурсивной функции? Для простоты вычисляются все тяжелые числа с
digits
цифрами и минимальной суммой цифрmin_sum
.Реализовано это в python, и он нашел все 9-значные числа за ~ 2 секунды. Немного динамического программирования может улучшить это.
источник
Это одно из возможных решений.
источник
C, для интервала [a, b] это O (ba)
//упражнение
//результаты
источник