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

Автор MacKenlly, история, 9 лет назад, По-русски

Я давно столкнулся с такой задачей, но на днях вспомнил о ней=) Требуется написать программу, которая уравнивает два числа a и b. Нужно использовать две операции +1 и *2 на двух числах. К примеру, числа 7, 13 ===> 14,14 (7*2,13+1) Все перепробовал... Может существует какой-то алгоритм? Я думаю что эта задача из раздела ДП. Проверочный тест — 14 62

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

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

Пусть a меньше за b, тогда к а будем добавлять 1 пока все его биты не совпадут с первыми битами числа b, после этого множим число а на 2 пока числа не уравняются и по ходу умножения добавляем 1 если len(a)+i ( len(a) — длинна в битах числа а) бит числа b будет 1 или не добавляем ничего. О(min(a,b)+log(max(a,b))) UPD: только сейчас заметил, что количество действий не будет минимальным :( так как не изменятся число b

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

ans[i] = min(ans[i + 1], ans[2 * i]) + 1, где i >= a — число, из которого надо получить число b, i + 1 и 2 * i <= b, ans[b] = 0
Либо же жадное решение — если b можно разделить на 2 и b / 2 >= a, то делим, иначе отнимаем b -= 1, т.е. обратный путь из b в a, не знаю, работает или нет

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

Пусть числа a и b.

Предположим, не нарушая общности, что a < b.

Тогда b - a раз сделаем следующее:

К a прибавим 1.

После этого числа станут равными.

Доказательство:

Пусть к числу a прибавили b - a раз по единице. Значит новое первое число будет равно:

a + (b - a)·1 = a + b - a = b.

Второе число равно b.

Доказано.

Код:

#include <iostream>
using namespace std;

int main()
{
    int a, b;
    cin >> a >> b;
    if (a > b)
        swap(a, b);
    for (int i = 0; i < b - a; ++i)
        ++a;
}

Также можно решать эту задачу с помошью динамического программирования. Приведу сразу код:

#include <iostream>
using namespace std;

int main()
{
    int a, b;
    cin >> a >> b;
    if (a > b)
        swap(a, b);
    vector<int> dp(b - a + 1);
    dp[0] = a;
    for (int i = 0; i < b - a; ++i)
        dp[i + 1] = dp[i] + 1;
    a = dp.back();
}

Надеюсь, что мой комментарий помог вам понять решение задачи.

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

    за один ход можно применять операции +1, *2 только один раз, операции с двумя числами

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

То есть за один ход обязательно применение по одной операции к обоим числам? (Авторы комментариев выше решали другую задачу, я спрашиваю только чтоб внести ясность). И было бы неплохо узнать ограничения.