Ответы пользователя по тегу Рекурсия
  • Как оптимизировать код с++ с рекурсией в времени?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно попробовать сделать микрооптимизации: функция F реализуется одним циклом (делите, пока делится на 10, потом берите последнюю цифру). S тоже можно считать циклом, а не рекурсией.

    Но скорее всего, этого не хватит. Это решение за O(q*log(q)). Ограничения на числа в условии не видно, но если там что-то порядка 2000000000, то ваша программа будет считать несколько секунд.

    Надо хорошенько подумать и применить математическую хитрость. Надо как-то считать числа в интервале p...q пачками, а не каждое отдельно.

    Что такое функция F? Это последняя ненулевая цифра в числе. Давайте вместо суммы значений F счиатать, сколько чисел из интервала дадут вот такое вот значение? Ну просто по последней цифре сложно сказать, сколько там чисел, а вот если еще зафиксировать количество пропущенных в конце нулей, то уже становится понятно, как подсчитать это. Вот допустим, вы считаете последнюю цифру d и там должно быть 3 нуля. Тогда вы ищети числа вида "xxxd000". Или их можно представить в виде d*1000+x*10000 для произвольного неотрицательного x. И вот вам надо подсчитать сколько таких чисел в интервале [p,q]. Ну решите 2 уравнения: d*1000+x*10000 >= p и d*1000+x*10000 <= q

    Таким образом вы за несколько арифметических действий и одну проверку можете подсчитать, сколько чисел вида "xxxd000" будут в интервале. Осталось циклом перебрать d от 1 до 9 и количество нулей от 0 до длины q. И вот у вас решение за O(log(q)).

    Edit:
    Вот код быстрого решения:
    int S(int p, int q) {
      int sum = 0;
      for (int d = 1; d < 10; ++d) {
        for (int tens = 1; tens <= q; tens *= 10) {
          int left = p - d*tens;
          if (left < 0) left = 0;
          else left = (left + 10*tens-1)/(10*tens);
          int right = q - d*tens;
          if (right < 0) right = -1;
          else right /= 10*tens;
          sum += d*(right - left + 1);      
         }
      }
      return sum;
    }
    Ответ написан
  • Как нарисовать кривую Серпинского (см. ниже), не используя графические библиотеки, а '*' или слешы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Напрягает требование, что нельзя использовать контейнеры. Так-то ваш подход правильный: Заводим поле для вывода, рекурсивной функцией, которой передаются порядок кривой, и где ее рисовать (квадрат и его поворот). Функция рекурсивно вызывает 4 кусокчка в каждом из 4 квадратов и рисует 3 соединительных кусочка. Но поле для вывода это так или иначе массив. Можно и самому его завести, но почему нульзя использовать контейнеры - не понятно.

    Второй вариант: релизовать функцию, которая (опять рекурсивно) считает какой символ вот на этой позиции в кривой вот такого порядка. Функция проверяет, лежит ли искомый символ между четырьмя квадратами. Если да, то сразу понятно - стоит там пустота или один из трех соединительных кусочков. В противном случае, рекурсивно вызываемся для нужного квадрата, пересчитав координаты, и может быть поворачиваем ответ на нужный угол.

    А потом циклом выводим результат работы функции для всех координат. Это работает в логарифм раз медленее, но зато не требует выделения памяти под все поле вывода.

    edit: Да, еще есть трюк - считайте, что кривая не замкнута. Левый верхний угол - пустота. И надо отдельно в самом конце замкнуть ее в этом углу через "/".
    Ответ написан
    6 комментариев
  • Как сделать рекурсивную функцию, которая находит сумму нечетных элементов динамического массива на C?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Ошибка в том, что вы проверяете на четность сами элементы, а не их индексы. Вы суммируете нечетные числа. Если надо каждое второе число брать, то проверяйте на четность n.
    Ответ написан
  • Как работает алгоритм перебора перестановок (рекурсия)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Перебирается число, которого еще нет в массиве. Ставится на следеющее место и рекурсивно запускается для каждого варианта.
    Ответ написан
    Комментировать
  • Путь коня или какова польза ограничений?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Есть простая оптимизация - из всех возможных ходов из текущей клетки перебирать сначала те, которые ведут в клетку с наименьшим количеством возможных следующих ходов (это надо проверить и все ходы через один ход и посмотреть, а обойдены ли те клетки уже). Эта оптимизация как раз заставит коня ходить сначала вокруг стенки и по спирали подходить к центру.
    Ответ написан
    5 комментариев
  • Как найти Среднее арифметическое элементов массива через рекурсию?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Подумайте, как можно рекурсивно считать сумму. Далее, среднее арифметическое элементарно выражается через сумму, а сумма - через среднее арифметическое. Вот и получается формула:

    Avg(a1,a2,...an) = (Avg(a2,...an)*(n-1)+a1)/n
    Ответ написан
    Комментировать
  • JavaScript - как проверить, есть ли в объекте циклические ссылки?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Поиск в глубину.

    Надо поддерживать список/множество уже посещенных вершин и пока посещаемых (те, что в стеке). При заходе в вершину в рекурсивной функции помещайте ее в множество пока посещаемых. При возвращении из функции перемещайте вершину в множество уже посещенных. В функции пройдитесь по всем ребрам, если они ведут в пока посещаемую вершину - вы нашли цикл. Если ребро ведет в уже посещенную - игнорируйте его. Если ребро ведет в не посещенную вершину - рекурсивно запускайтесь от нее.
    Ответ написан
    Комментировать
  • Каким образом можно сделать рекурсивную функцию кластеризации объектов?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    У вас есть граф, где вершины - теги, и есть ребра между ними. Если брать ребро там, где два тега не совместимы, то у вас задача поиска клик.

    Во первых, тут есть неоднозначность. Может быть так что теги A,B,C попарно несовместимы, но заодно попарно несовместимы теги A,D,E - куда относить тег A, в какую группу?

    Поиск самой большой группы - сложная задача тут нет простых алгоритмов. Полный перебор и всякое тому подобное тут работает.

    Если надо просто достаточно большую группу найти, то можно делать жадно. Есть текущая "цепочка несовместимых тегов", есть какие-то уже откинутые теги, есть какие-то оставшиеся, вот берите любой из оставшихся и, если он подходит, то добавляйте его к несовместимым тегам. Если нет - отбрасывайте.

    Еще есть Алгоритм Брона — Кербоша. Он перебирает все максимальные клики.
    Ответ написан
  • Как решить задачу по рекурсивным алгоритмом на python?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вы, похоже, забыли обнулять счетчик восьмерок (k) для каждого значения f.
    Ответ написан
    Комментировать
  • Почему рекурсия неверно отрабатывает?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ваша программа ломается, если X=Y, например.
    Чтобы ее исправить, вместо веса edge и сравнения его со стоимостью товара, передавайте в функцию число от 1 до 3. Если число <=1, то можно брать x и передавать 1. Если <=2 - то можно брать y и передавать 2, и т.д.
    Ответ написан
    2 комментария