Блог пользователя heavenly_phoenix

Автор heavenly_phoenix, 10 лет назад, По-русски

Вопрос на ДП. Идей нету как решать этот вопрос. Благодарен за помощь.

  • Проголосовать: нравится
  • +1
  • Проголосовать: не нравится

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

В общем, динамика у тебя будет dp[S][K] = количество способов разбить число S в K слагаемых. Пересчет за куб: перебираешь сумму, число, которое ты сейчас добавишь, и количество слагаемых(то есть K).

Пересчет можно делать, например, так: dp[S + curr][K + 1] += dp[S][K]

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Спасибо

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    но подождите к чему равно curr

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      В curr ты перебираешь значения от 1 до N. Ограничения 150 же.

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        но отличающиеся только порядком слагаемых считаются одинаковыми

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Как вариант, можно ввести третий параметр: последнее слагаемое, которое мы взяли. Тогда добавится один цикл еще. И мы всегда делаем пересчет из предыдущего слагаемого, меньшего или равного текущему. Это 5*10^8. Возможно, уложится в секунду.

          • »
            »
            »
            »
            »
            »
            10 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Данную идею можно реализовать и за куб. Перебираем сумму S, число слагаемых K, последнее слагаемое T. Тогда
            DP[S][K][T] = sum(DP[S - T][K - 1][X]: X ≤ T)

            Последнее можно пересчитывать частичными суммами.

»
10 лет назад, # |
  Проголосовать: нравится +14 Проголосовать: не нравится

Можно вывести следующее рекуррентное соотношение: P(n, k) = P(n - 1, k - 1) + P(n - k, k) и решать задачу за O(nk).

Рассуждения имею следующий вид: упорядочим все слагаемые. Теперь посмотрим на наименьшее и разобьём все разбиения на два класса — те, у которых оно равно единице (таких будет P(n - 1, k - 1)) и те, у которых оно не равно единице. Чтобы посчитать количество вторых, воспользуемся следующим трюком — вычтем из всех слагаемых единичку. Теперь их число можно определить как P(n - k, k).