Задать вопрос
  • Как разложить число на множители(си)?

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


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

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Возьмите для каждого товара набор точек {день, показатель} за сколько-то последних дней. Постройте линейную регрессию. Наклон прямой (т.е. коэффициент перед номером дня) и будет этим показателем динамики.
    Ответ написан
    Комментировать
  • Не компилируется код?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    У вас операция присвоения лежит вне функции. Компилятор ждет там декларации переменных, функций, типов, вот это вот все, а у вас там операция. Перенесите присвоение в main().

    Если вы хотите структуру инициализировать, то можно пользоваться списком инициализации:
    struct {
            int debug;
    } config = {1};
    Ответ написан
    Комментировать
  • Как найти полусумму 32-битных знаковых чисел?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Прочитать бинарно не можете? Есть функция read.

    Читайте ей по 4 байта 2 раза в char buf[4].

    little-endian означает, что сначала идут самые минимальные байты. Т.е. buf[0] - это младшие 8 бит числа, buf[3] - старшие. Для собирания числа воедино смотрите на операцию сдвига. (int)buf[3] << 24 | (int)buf[2] << 16 поставит на место 2 старших байта (младшие додумайте сами).

    Тип 64-х битных чисел - long long. Вам в условии посоветовали им пользоваться.

    Сложить 2 числа сами сможете?

    Бинарный вывод делается, внезапно функцией write.

    Ну, еще входной и выходной файлы, возможно, открыть придется, через функцию fopen.
    Ответ написан
    3 комментария
  • Как посчитать вероятность того, что конкретная подстрока встретится во всей строке только 1 раз?

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

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

    Вот построили вы автомат. Теперь задача состоит в том, чтобы найти вероятность, что случайный путь в этом автомате длины n пройдет через конечное состояние ровно один раз. Для этого подсчитайте 2 вероятности: что путь из начала длины k дойдет до конечного состояния один раз, и что путь из конечного состояния длины n-k не вернется в него.

    Обе эти вероятности можно подсчитать динамическим программированием:
    P1(i, k) - вероятность того, что путь начиная с состояния i (i < n) за k шагов дойдет до состояния n первый раз. Это просто сумма по всем возможным переходам:

    P1(i, k) = sum_{c - все символы} P1(next(i, c), k-1) * p(c)

    База:
    P1(m, 0) = 1
    P1(m, k>0) = 0
    P1(i < m, 0) = 0


    Вторая вероятность: сделать k шаговиз состояния i и ни разу не войти в конечное состояние:
    P2(i, k) = sum_{c - все символы, next(i,c) < m} P2(next(i, c), k-1) * p(c)


    База:
    P1(i, 0) = 1

    Ответ к задаче - сумма по всем возможным длинам первой части пути:
    sum_{k=m..n} P1(0, k) * P2(m, n-k)

    Это решение через динамическое программирование будет O(n*m) по вермени и по памяти.

    Замкнутой формулы, как в задаче в моей статье я тут не вижу. Может, если бы вероятности всех символов были бы одинаковы, то что-то можно было бы сократить.
    Ответ написан
    2 комментария
  • Как получить координаты точки, если известны координаты трёх других точек и расстояние от этих точек до искомой точки?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Вам просто надо пересечь 3 окружности на плоскости. По "формула пересечения окружностей" гуглится, например, это или это.

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

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

    Все ваши ключи складываете в бор, как описано по ссылке. Потом для каждого кортежа выполняйте поиск в строке i[1], если нашли, то добавляйте ваш id в ответ.
    Ответ написан
    3 комментария
  • Как построить функцию декодирования классического кода Элиаса, если прямое кодирование работает правильно?

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

    И читайте это:
    1) подсчитайте сколько нулей идет в начале строки.
    2) Это сколько бит надо прочитать дальше и перевести в десятичную систему счисления.
    3) Это столько бит, сколько нужно прочитать дальше и перевести в десятичную систему, чтобы раскодировать число.
    Ответ написан
    Комментировать
  • Как сортировать массив с рандомными значениями?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    for(d=0; d < n; d++)
      x[i] = rand();
     printf("%d", x[i]);


    Цикл по d а присваивание в x[i]. Еще скобок нет, printf выполнится только один раз после цикла.

    Еще вы не выводите массив после сортировки, как вы вообще собираетесь понимать, что ваша программа работает?

    В самой сортировке (циклы по i и j), вроде, ошибок нет.
    Ответ написан
    Комментировать
  • Почему после очистки строки программа падает?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вы очищаете msg_buf в цикле же. На второй итерации у вас msg_buf уже очищен и вы его передаете в realloc и все падает.

    Попробуйте после free присвоить msg_buf = NULL.
    Ответ написан
    Комментировать
  • Как найти количество перестановок числа?

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

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

    Еще, в вашей формуле направшивается добавить пустое число ("") в ответ. Давайте разрешим его и вычтем в конце 1.

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

    Поэтому пусть f(a0,a1,...a9) - сколько есть способов расставить некторые из a0 нулей, a1 единиц, a2 двоек, и т.д. (ноль может идти в начале, число может быть пустым).

    Ответ к задаче f(a0,a1,...a9)-1-min(a0,1)*f(a0-1,a1,...a9). Последнее слагаемое считает варианты, начинающиеся с нуля. Оно не вычитается, если нулей в числе нет. -1 посередине вычитает пустое число из ответа (но ее нет в последнем слагаемом, ведь мы там еще 0 в начале приписываем и пустое число надо считать).

    Теперь самое интересное, формула для f(a0,a1,...a9). Замкнутой формулы я не нашел, но придумал, как считать алгоритмом.

    Можно все варинаты разделить по количеству символов в числе (n), от 0 до суммы a0...a9. Давайте подумаем, где могуть быть девятки? i <= a9 из них попадут в ответ. Они могут быть на C(n, i) позициях. Останется разместить остальные цифры на n-i позиций.

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

    F(i, n) - сколько способов разместить первые i цифр на n позициях (возможно, беря не все цифры).

    F(i,n) = sum (j=0..min(a[i-1], n)) F(i-1, n-j)*C(n, j)
    F(0, n>0) = 0
    F(i,0) = 1.
    Ответ - sum(k=0..a0+...+a9) F(9, k)

    У функции как бы неявный параметр массив a[] количеств всех цифр, но я его не включаю в параметры динамики, потому что по нему не надо мемоизировать.

    Не забудьте, что для подсчета второй динамики, для f(a0-1,...a9) надо будет полностью отчистить мемеоизацию, потому что массив a поменялся же.

    Этот алгоритм работает за O(9*n), где n - длина входного числа.

    Вот пример для входного числа 112: все цифры, которых в числе нет можно выкинуть из рассмотрения и работать с массивом a={2,1} (для всех десяти цифр слишком много писать).

    F(0,0) = 1
    F(0,1) = 0
    F(0,2) = 0
    F(0,3) = 0
    F(1, 0) = 1
    F(1,1) = F(0, 1)*C(1,0) + F(0,0)*C(1,1) = 1
    F(1,2) = F(0,2)*C(2, 0)+ F(0,1)*C(2,1) + F(0,0)*C(2,2) = 1
    F(1,3) = F(0,3)*C(3, 0)+ F(0,2)*C(3,1) + F(0,1)*C(3,2) = 0
    F(2,0) = 1
    F(2,1) = F(1,1)*C(1, 0) + F(1,0)*C(1,1) = 2
    F(2,2) = F(1,2)*C(2, 0) + F(1,1)*C(2,1) = 3
    F(2,3) = F(1,3)*C(3, 0) + F(1,2)*C(3,1) = 3

    Ответ F(2,3)+F(2,2)+F(2,1)+F(2,0) = 3+3+2+1= 9.

    Вычитаем 1 (пустое число) и получаем 8 чисел, как у вас в примере для 112.
    Ответ написан
    2 комментария
  • Почему одни, незначащие скобочки, меняют ответ?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас i - целое, а x - вещественное. При делении целого на целое идет деление нацело (с округлением вниз до целого). При делении целого на вещественное или вещественного на целое - результат вещественное.

    Если лишние скобки поставить, то у вас сначала происходит деление нацело (2*i+1)/(2*i), а потом домножение на вещественное.
    Без скобочек операции выполняются слева направо - a *(-1*x)*(2*i+1) даст вещественный результат, который точно поделится.

    Если вы в скобочках приведете к вещественному, то у вас тоже все заработает: a = a *(-1*x)*((2*i+1.0)/(2*i));
    Ответ написан
    Комментировать
  • Какие два числа до 60 наименее кратны друг другу в прогрессии?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Не очень понятно, но вам, похоже, нужны такие числа, чтобы у них был максимальное наименьшее общее кратное (это то самое 42 для 6 и 7).

    Из чисел до 60, очевидно, вам подходят числа 60 и 59 - у них нет общего делителя и НОК равен просто их произведению (3540). Если нужно строго меньше 60, то берите 58 и 59. Вообще, 2 максимальных числа в промежутке будут вашим ответом. У соседних чисел НОК всегда равен их произведению и произведение двух максимальных в отрезке будет самым большим возможным значением.
    Ответ написан
    1 комментарий
  • Как проверить, попадает ли географическая точка в правильный шестиугольник?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Вычтите координаты центра из координат точки. Теперь шестиугольник лежит центром в (0, 0).

    Составьте 6 уравнений сторон шестиугольника в виде Ax+By+C=0, так что C положительно (если нет - домножте на -1). Подставьте в эти 6 уравнений координаты точки, все они должны дать положительные значения (или нули, если точка на границе считается лежащей внутри в вашей задаче).

    Почему это работает? Мы просто проверяем, что точка лежит с той же стороны от всех 6 прямых, что и центр (0, 0).

    Как составить уравнения? Найдите координаты 6-ти углов. Если сторона = a, то координаты точек (a, 0), (a/2, sqrt(3)*a/2), (-a/2, sqrt(3)*a/2), (-a, 0) ...

    Для уравнения одной из сторон возьмите в виде A разность по у у соседних точек, а в виде B разность по x (но с другим знаком). Потом подставьте туда координаты одной из точек и возьмите C так, чтобы был 0.

    Можно все 6 уравнений составить на бумажке и закодировать в программе.

    Пример для первой стороны:
    A = sqrt(3)*a/2-0 = sqrt(3)*a/2
    B = a - a/2 = a/2
    C = -A*a - B*0 = -sqrt(3)*a*a/2.

    Поскольку C отрицательно, меняем знаки:
    A = -sqrt(3)*a/2
    B = -a/2
    C = sqrt(3)*a*a/2

    Для второй прямой будет 0*x-a*y+sqrt(3)*a*a/2 = 0

    И да, это работает, если предположить, что шестиугольник маленький или на плоскости. если у вас кривизна земли играет роль, то все сильно усложняется.
    Ответ написан
  • Можете пожалуйста написать на С++ произведение сумм?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам надо перед циклами инициализировать переменные-аккамуляторы: Перед циклом по i нужно присвоить y = 1. Перед циклом по j нужно присвоить sum = 0.

    Иначе у вас в sum накапливается сумма для всех разных i. А y вообще непонятно какое значение имеет до домножения.
    Ответ написан
  • Python. Найти расстояние от точки до прямой, зная координаты этой точки?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Составьте уравнение прямой вида a*x+b*y+c=0.
    Подставьте в это уравнение координаты точки. Возьмите по модулю и поделите на sqrt(a^2+b^2).
    Ответ написан
    Комментировать
  • Как портировать линуксовое консольное приложение под Windows?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Можно попробовать какой-нибуть mingw поставить. Получается какбы линуксовая оболочка в винде. Можно компилить в ней исходники, получающийся exe-шник автоматом получит транслирование системных вызовов. Нет гарантии, что любой код заведется, но шансы есть.

    Т.е. виндовые исходники вы не получите, но есть вариант скомпилить эти линуксовые исходники в exe-шник, который, возможно, потребует установки mingw на машину, где приложение будет работать.

    Edit, возможно mingw тут не поможет и нужен cygwin. Еще был какой-то msys. Но я не уверен.

    На худой конец, под 10 виндой есть WSL.
    Ответ написан
    8 комментариев
  • Как быстро найти вершину,которая имеет наибольшее количество ребер и не соединена с данной вершиной?

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

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

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

    Но в этой задаче можно проще: Найдите все вершины с максимальной степенью. Если из 3 и более, то найдите среди них 2 не связанные (берете любую, потом еще одну любую. Если они связанны, то берите любую третью - она не связанна с одной из двух первых).

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

    Также рассмотрите в качестве варианта ответа пару соседей для максимальной вершины, если она одна. Это выбрать в массиве 2 наибольших числа - делается за линию.

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

    Теперь рассмотрим случай двух связанных максимальных вершин. Рассмотрим оптимальный ответ. Если в нем нет одной из максимальных вершин, то мы могли бы заменить один из концов на максимум. Мы не можем этого сделать, только если оба конца связанны с обоими максимумами, а это означало бы циклы в графе. Но у нас же дерево! Значит, оптимальный ответ обязательно содержит одну из максимальных вершин. Но мы этот вариант в алгоритме перебрали.

    Остается случай из одной максимальной вершины. Опять же оптимальный ответ не содержит ее, только если его нельзя улучшить - а значит оба конца связанны с максимальной вершиной. Но этот случай мы тоже разобрали.
    Ответ написан
  • Сколько элементов массива больше своих соседей (предыдущего и следующего элементов)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Чтобы пропустить первый и последние элементы просто измените границы цикла:
    for (int i = 1; i < 24; i++)

    Если вы хотите эти элементы считать, если они больше единственного их соседа, то воспользуйтесь ленивым вычислением логических формул (при вычислении A || B, если A == true, то B вообще вычисляться не будет):
    for (int i = 0; i < 25; i++)
      {
        if ((i +1 == n || ARR[i] > ARR[i + 1]) && 
             (i == 0 || ARR[i] > ARR[i - 1]))
          count++;
      }
    Ответ написан
    1 комментарий
  • Правильно ли я понимаю запись через сигму?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Y у вас из множества R^W*H*2. Т.е. Y состоит из W*H*2 чисел проиндексированных тремя индексами - первый до w, второй до h, третий до 2. Соответственно в формуле считается сумма по всем значениям первых двух индексов. Y_wh - это пара чисел. У вас множества в примере неправильно составлены - там вместо a и b должны быть пары чисел.

    Далее, нижний индекс 2 после || - это обозначение нормы L2 в двумерном пространстве - это корень второй степени из суммы квадратов (обычное декартово расстояние). Верхний индекс после || - это просто возведение в квадрат, который отменяет извлечение корня для ||...||_2.

    Т.е. Вся эта формула говорит взять W*H*2 покомпонентные разности, возвести их в квадрат и сложить.
    Ответ написан