Задать вопрос
  • Поможете сделать код лучше, чем у меня сейчас, a³+b³=c³?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    2. Этот код не для Windows;


    Там нет ничего платформо-зависимого. Если установите какой-нибудь mingw на windows, то оно makefile съест.

    В крайнем случае, установите любой C компилятор и введите команду вручную (последняя строчка тут)

    3. Если я в формуле a³+b³+c³=3 поменяю 3, на 0 будет ли программа правильно считать?

    Там в описании написано "cubefree k = +/- 3 mod 9 at most 1000", т.е. для k=0 не сработает.

    Поможете сделать код лучше?


    Выкиньте цикл по c. Вам не надо его перебирать, а вам надо решить уравнение c³=3-a³+b³.
    Для чего просто вычислите значение справа, потом возьмите кубический корень: int((3-a**3-b**3)**(1/3.0)). Не забудьте только проверить, что это значение c подходит, ибо тут корень округляется до целого. И не факт, что уравнение выполняется.
    Ответ написан
  • Насколько хорошая практика использовать обертки над операторами?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    В библиотечных функциях - можно так сделать. В смысле, ваши функции используют непубличную функцию, передавая ей оператор.

    Но вы этот оператор передаете всего в нескольких местах на всю кодовую базу и все. Писать так функции, которые вы используете кучу раз - очень плохая идея.

    И вообще, довольно редко есть смысл так заморачиваться. Код становиться хуже поддерживаемый. Экономите вы совсем чуть чуть повторяемого кода. А потом придется всякие заморочки делать, вроде, в делении надо проверять на 0, а в умножении проверять на переполнение и т.д. Этот общий код становиться уже чуть ли не длиннее если все по отдельности делать. И уж точно хуже читаемый.
    Ответ написан
    Комментировать
  • Алгоритм поиска маршрута?

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

    Это будет быстрее, чем самостаятельно реализовывать какой-нибудь алгоритм Дейкстры или обход в ширину, ибо питон - безбожно тормознутый язык. А в библиотеке вычисления обычно реализованы на более быстрых языках.
    Ответ написан
    1 комментарий
  • Как решить эту задачу?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    У вас 7 неизвестных и 3 уравнения. Так что однозначно вы найти значения переменных никак не сможете. Но и найти вам надо какую-то сумму. Есть шанс, что как-то комбинируя, складывая, вычитая и домножая левые части этих уравнений можно получить искомую сумму. Иными словами, вам надо вектор (16, 25..100) представить в виде линейной комбинации векторов (1, 2..49), (4, 9..64) и (9, 16..81). Обратите внимание, что там везде получаются суммы трех квадратов равны следующему.

    Вам надо подобрать такие 3 коэффициента, что x*n^2 + y(n+1)^2+z(n+2)^2 = (n+3)^2. Для n=1..7. У вас тут квадратные многочлены от n получаются, равны они в 7 точках, так что они должны быть равны вообще при любых n. Значит, вам надо раскрыть скобки, сгрупировать степени n и приравнять к 0 все коэффициенты.

    Так вы получите 3 уравнения на 3 переменные x, y, z.
    x+y+z=1
    2y+4z=6
    y+4z=9

    Отсюда получается x=1 y=-3 z=3

    В итоге получаете 1*1-3*12+3*123 - это ваш ответ.
    Ответ написан
    2 комментария
  • Какой самый быстрый способ найти позицию последовательности 0-bit заданной длины в int[]?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Зависит от длины n. Если n маленькое то можно прикладывать маску. Байт x содержит 3 ноля в последних битах, если ~x &0x7 == 0x7. Аналогично, сдвигая маску из трех единиц (0x7) можно приложить ко всем позициям.

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

    Потом, можно еще распараллелить поиск в несколько потоков. Каждый поток ищет последовательность, начинающаюся в отдельном куске массива.
    Ответ написан
    Комментировать
  • В чем заключается суть бинарного поиска неотсортированного массива?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ну ведь тут массив же отсортирован. Хоть и с приколом: он сдвинут. Можно тем же бинарным поиском найти, где там "разрыв" происходит, а после у вас 2 отсортированных куска. Или сразу модифицировать бинпоиск.
    Представьте, что у вас массив, где сначала идут 1, а потом 0. Можете найти в нем, где 1 переходит в 0?

    Или смотрите так: ищите вы x. Взяли значение a[m]. Можете, посмотрев на a[l], a[m], a[r] и x понять, в какой половине лежит x?

    Edit: ах, тут числа могут быть одинаковыми. Тогда бинпоиск тут не работает. Ибо может быть тест {1,1,1,2,1,1} - и тут можно 2 в любую позицию поставить. И, если вам надо эту 2 найти, то вам придется просмотреть все числа, иначе вы ее не найдете. Бинпоиск возможен, если первое и последнее числа разные.
    Ответ написан
    3 комментария
  • Как на udp сервере подсчитать one-way latency и верменной offset клиента?

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

    В итоге сервер получит 4 таймстампа: сервер отправил, клиент получил, клиент отправил, сервер получил. При этом два серверных и два клиентских - могут быть в разных часах. Поэтому надо взять t4-t1+t2-t3 - и вы получите rtt. Поделите на 2, получите оценку нужной задержки. И это надо сглаживать по многим пакетам.

    Проблема будет, если часы тикают с разной скоростью, а не просто отстают на фиксированное время. Это надо смотреть на динамику t2-t1. Если там линейная регрессия с отличным от 1 коэффициентом получается, то надо это учесть и делить на этот коэффициент t2-t3 в формуле. Но это редко делают. Если время обработки пакета клиентом мало по сравнению с сетевой задержкой, то лишь малая часть этого времени пойдет в ответ ошибкой.

    Однако, если вы часы синзронизируете, то вам надо постоянно пересчитывать отставание по последнему пакету и оценке rtt. И этот сдвиг часов будет изменятся со временем а соответствии с разной скоростью часов.
    Ответ написан
    Комментировать
  • Какой структурой можно повесить lock на диапазон?

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

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

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

    Тут операция выделения сама по себе будет сильно быстрее. Но это фактически спинлок - каждый поток будет в цикле пытаться выделить себе интервал, пока не сможет. Если ожидается, что потокам придется долго ждать, то надо какие-то стратегии back-off добавлять (спать между вызовами). И вообще спинлоки - это плохо.

    Как сделать это без спинлоков с деревом отрезков - я не придумал.
    Ответ написан
    Комментировать
  • Как показать зависимость скорости от O(nlogn)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Можно, только надо числа брать побольше. Скажем, 100000 и 1000000. Для полносты картины можно взять несколько точек. Еще возьмите, например, 5000000 и 10000000.

    Но вообще сложность алгоритма обычно доказывают логически. Типа, у вас там n операций с кучей, каждая операция ограничена O(log n) - потому что она проходит по бинарному дереву с менее чем n листьями, а значит, высотой менее log n.
    Ответ написан
  • Ошибка double free or corruption (out) Aborted, как исправить?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы никакого free и даже delete или new в программе не делаете. Значит ошибка в том, что структуры менеджера памяти как-то портятся. Это значит, что вы пишите куда-то за границы массива.

    Можно попытаться запустить программу в отладчике, или добавить кучу отладочного вывода, чтобы посмотреть, что и как вы портите.

    Подозреваю, что ошибка тут:
    int mli=index(len,ml),mpi=index(len,mp);
    Обратите внимание на второй вызов index. Вы ищите в массиве len значение mp, которое вы нашли в массиве price. Возможно оно возвращает -1 и дальше уже вы пытаетесь что-то делать в векторе по этому индексу, что вряд ли закончится хорошо.
    Ответ написан
    Комментировать
  • Почему постоянно выводится расстояние 0(Алгоритм Дейкстры для городов)?

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

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ага, ДП тут отлично входит. F(n) - ответ на задачу для префикса длины n. Там перебираете длину последней группы x и берете в качесвте ответа max(a[n-x]..a[n-1]) - min(a[n-x]..a[n-1]) + F(n-x). По всем l<=x<=r выбераете максимум. Если n < l, то ответ - минус бесконечность.

    Это будет решение за O(n^2). Что-нибудь за O(n log n) я так сходу придумать не могу.
    Ответ написан
    6 комментариев
  • Как в C++ создать массив с неизвестным числом элементов?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно через new[] выделить массив:
    cin >> n;
    int *array = new int[n];
    // ввод, и работа с массивом.
    
    // не забудьте в конце удалить выделенную память.
    delete[] array;
    Ответ написан
  • Как оптимизировать код с++ с рекурсией в времени?

    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 Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Минимизируйте стоимость строительства самой дорогой построенной предложенной линии.


    не сумма всех взятых ребер, а стоимость максимального из них.

    1 2 (2) и 2 3 (1) - максимальная стоимость 2 (max(1,2)).

    1 3 (3) - максимальная стоимость 3 max(3). 3 больше 2, значит ответ выше лучше.

    Так задача легче, чем с суммой.
    Ответ написан
    8 комментариев
  • Какую формулу использовать?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Можно делить на цело в конце. 110*300/330 даст ровно 100. Если же в котле осталось не делящееся нацело количество монет, то будет округление вниз: для 301 монеты тоже получится 100 вместо 100.(3).

    Надо хранить долю юзера в виде рационального числа - отдельно числитель и знаменатель.
    Ответ написан
    Комментировать
  • Справится ли алгоритм с задачей по поиск слов в словаре?

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Внутренние циклы выполняют суммарно максимум 8(r-l-1) операций. На каждой итерации внешнего цикла r-l уменьшается на 2. Т.е. всего операций будет 8(n-2)+8(n-4)+8(n-6)...

    Можете эту арифметическую прогрессию подсчитать и оценить?
    Ответ написан
    Комментировать
  • Как вернуть двумерный массив?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    int masInt[3][5] - вот такие массивы c фиксированными размерами на самом деле хранятся одним куском и индексацию компилятор вычисляет сам. Это не int**, а int[][5]. Только этот тип нельзя вернуть из функции.

    Что бы вернуть именно указатель на указатель, вам надо его так и завести и не забыть выделить по строкам:
    int** masInt = new int* [3];
    for (int i = 0; i < 3; ++i) {
      masInt[i] = new int[5];
    }


    Не забудьте только потом удалить все это добро через delete[]:
    for (int i = 0; i < 3; ++i) {
      delete[] array[i];
    }
    delete[] array;


    Но вообще, лучше не парить себе мозги и возвращать std::vector<std::array<int,5>>.
    Ответ написан
    1 комментарий