Re: Делимость числа и сумма его цифр.
От: Vintik_69 Швейцария  
Дата: 15.03.12 17:49
Оценка: 9 (2)
Здравствуйте, Assasin291, Вы писали:

A>Здравствуйте. Есть задача: на вход поступают числа A, B, S, T, k, где

A>1 <= A, B <= 10^19;
A>1 <= S, T <= 162;
A>2 <= k <= 100.
A>Нужно найти количество всех чисел, которые находятся на интервале [A, B], имеют сумму цифр, принадлежащих отрезку [S, T] и в то же время делятся на k без остатка.

A>Прямой перебор здесь не подходит. Как можно поступить в таком случае?


Это довольно стандартная задача на динамическое программирование.

Во-первых, научимся находить количество чисел <= X, обладающих всеми свойствами относительно суммы цифр и делимости. Пусть таких чисел будет F(X). Тогда ответ на исходную задачу будет F(B) — F(A-1). Теперь, как искать F(X)?

Пусть X у нас задано, и в нем n цифр. Будем искать все n-значные числа с заданной суммой и делящиеся на k. Представим что мы записываем число слева направо (со старших разрядов). Допустим, мы записали уже i цифр. Тогда нас интересуют следующие свойства записанного числа: остаток от деления на k (обозначим q), сумма цифр (обозначим s) и то, гарантирует ли записанный префикс, что любое число с этим префиксом меньше X (обозначим l, это булевский флаг). Посчитаем количество чисел которые можно получить из префикса длины i с остатком q, суммой s и флагом l, так чтобы они удовлетворяли всем условиям задачи и были меньше X. Обозначим это количество как F(i, q, s, l).

Тогда какие у нас варианты? Если l == true, то есть префикс заведомо меньше X, мы можем приписать любую цифру справа. Получается:

F(i, q, s, true) = sum(d in [0..9], F(i+1, (q*10 + d) mod k, s + d, true)

Если l == false:

F(i, q, s, false) = sum(d in [0..X[i]], F(i+1, (q*10 + d) mod k, s + d, d < X[i])

Где X[i] — это i-я цифра числа X (нумерация с 0, 0 — самый старший разряд).

Тогда F(X) = F(0, 0, 0, false)

начальные условия:

F(n, q, s, l) = 1 if q == 0 and S <= s <= T else 0, где n — длина числа X.

Получилась рекуррентная формула, которую осталось только запрограммировать (с мемоизацией).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.