Задать вопрос
  • Как добавить в `std::map` объект с константными полями?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Храните в std::map указатели на ваш тип. Лучше умные, вроде shared_ptr.
    Ответ написан
  • Выводятся какие-то цифры и ошибка, что не так?

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

    Смотрите внимательно, где вы к нему обращаетесь. Особенно на arr[j + 1]. Какие значения может принимать j? Какой размер массива и, соответственно, к каким индексам можно обращаться?
    Ответ написан
    Комментировать
  • Как определить, можно ли из символов первого массива создать строку идентичную второму массиву?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Подсчитайте, сколько каждого символа встречается в первой строке и убедитесь, что во второй - их не больше.
    Самый простой способ сделать это - это завести массив счетчиков на 256 элементов. Для символов первой строки увеличивайте счетчик по индексу static_cast<int>(s[i]) на 1, для второй строки - вычитайте 1. Если где-то получили -1, то составить нельзя.

    И еще, это же у вас C++, судя по тегам и cin? Ну так используйте std::string. Зачем вы сишные строки выделяете?
    Ответ написан
    Комментировать
  • Как эффективно найти все объекты, у которых в названии есть все заданные слова?

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

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

    Если же вы можете один раз что-то предподсчитать для всех магазинов, то потом можно выполнять "запросы" даже не проходясь по всем магазинам.

    Можно по каждому тегу составить список магазинов, имеющих его в названии, упорядоченный как-то (допустим, по id магазинов). Эту структуру можно построить за один проход по всем магазинам и сохранить.

    Затем ваш запрос на пар тегов можно обрабатывать объеденяя и пересекая упорядоченные списки. Эти операции, как в сортировке слиянием, делаются за один проход по списку.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Функция вывода на экран - printf(). Один символ или строку, которую вам надо вывести надо передать туда одним параметром в кавычках, например printf("1");.
    Чтобы сделать перевод строки надо вывести символ "\n". Можно добавлять его в конец строки, например printf("44\n");
    Ответ написан
  • Определить победителя КНБ?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    (-1) % 3 = 2

    Это математическое определение вычетов по модулю. Все числа, которые отличаются на n, имеют одинаковый остаток по модулю n. Конфуз происходит из-за того, что операция взятия по модулю во многих языках программирования работает не так. Для отрицательных чисел она выдаст отрицательное значение, правда к которому можно прибавить n, что бы получить правильный модуль - число от 0 до n-1.

    Поэтому при реализации можно делать (a-b+3)%3 Или преобразовать, чтобы не было вычитания: b == (a+1)%3
    Ответ написан
    Комментировать
  • Односвязные списки. Удаление элемента?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Только если вам известен ПРЕДЫДУЩИЙ элемент. Иначе за честные О(1) вы из односвязного списка ничего не удалите.

    Можно амортизационно удалить за О(1) просто пометив этот элемент удаленным. Но тогда все функции, которые проходятся по списку, должны такие помеченные элементы действительно удалять во время прохода.

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

    Но на практике этот метод, наверно, не применяется. Потому что вы же где-то берете указатель на удаляемый элемент. Обычно можно вместе с ним получать и указатель на предыдущий. Или тупо использовать двусвязные списки.
    Ответ написан
    1 комментарий
  • Формула повышения уровня игры?

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

    Попробуйте что-то вроде 1.2**lvl *50 и 1.3**lvl *100.
    Ответ написан
  • Безопасно ли здесь использование функции printf?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Безопасно.
    Ответ написан
    Комментировать
  • Насколько мой код читабелен?

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

    Вместо набора функций, которые возвращают и принимают IntList1D, стоит завести класс, который содержит в себе указатель на начало списка. У этого класса должны быть методы initalize, is_initialized, pushBack, и т.д. Это сократит код немного и сделает его гораздо более логичным.

    Тип элемента списка вы объявляете как приватный класс-член в классе списка, и он не будет засорять пространство имен пользователей вашей библиотеки. Им о нем вообще знать не надо, они хотят в ваш список класть int и получать назад int.

    Далее, вы пишите контейнер, в идеале его стоит сделать по образу и подобию стандартных контейнеров. С итераторами и т.д. Чтобы с ними было можно работать точно также. Но, если не потянете, то хоть обзовите методы также, как у стандартных (push_back(), empty(), см std::vector, например).

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

    Потом, часть функций называется частично большими буквами, частично строчными. Это вообще зачем? APPEND_FRONT_Link? Соблюдайте единый стиль хотябы в одном названии. Если они отличаются от appendFront тем, что они не предназначены для пользователей библиотек, ну так это как раз аргумент в пользу использования классов. Делаете эту функцию приватным методом. И такие обычно называются с суффиксом Impl (от implementation) - appendFrontImpl.

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

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

    Первый член - 1 (при j=i+1), последний - n-i (при j=n). Всего их n-i. Ну а дальше - стандартная формула: среднее крайних членов, помноженное на их количество.

    Как из этого получается O(n^3). По уму, надо раскрыть скобки и разложить на сумму трёх рядов, в зависимости от степени i в слагаемом. Дальше сумма i даст также O(n^2). Сумма по i^2 даст O(n^3). Тут уже нельзя арифметическую прогрессию применять, но это известная формула - сумма n квадратов даст n(n+1)(2n+1)/6. Ее можно вывести, если взять ряд f(x)=1+x+x^2+...+x^n = (1-x^{n+1})/(1-x) и найти (x*f'(x))'. Потом туда можно подставить x=1. Или есть визуальные доказательства. Каждый квадрат - это квадрат из кубиков. Их все можно сложить в пирамиду. 6 таких пирамид можно сложить в параллелепипед.
    Ответ написан
    1 комментарий
  • Как посчитать число 2 в 1 000 000 000 000 000 степени?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    2^10 ~ 10^3. 2^1 000 000 000 000 000 ~ 10^300 000 000 000 000.

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

    Вряд ли у вас цель - получить эти 300 миллиардов цифр. Наверно, вам нужно что-то с этим числом делать. Возможно, это можно сделать без вычисления всех цифр числа. Например, если вам нужны последние 100 цифр - то можно на том же питоне производить вычисления по модулю 10^100. Правда, придется писать экспоненциальное возведение в степень самостоятельно.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать для определения нахождения точки за границей треугольника пространства?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Если точка не на плоскости треугольника, то вам надо переформулировать задачу. Там вообще непонтяно, что значит внутри/снаружи.

    Если же оно на плоскости, то введите там систему координат (например, орто-нормируйте вектора p2-p1 и p3-p1). Получите координаты всех точек (p1 можно назначить началом координат).

    Потом придется применять формулу для плоскости. Можно воспользоваться векторными произведениями. Произведение пар векторов {p-p1, p2-p1}, {p-p2, p3-p2}, {p-p3, p1-p3} должны все давать одинаковый знак (или все <=0 или все >=0. Равенство 0 чего-то будет означать, что точка на границе).

    Или можно посчитать площади, опять же через векторное произведение. |(p2-p1)(p3-p1)| = |(p1-p)(p2-p)+(p2-p)(p3-p)+(p3-p)(p1-p)|
    Ответ написан
  • Как заставить потоки работать с классом с++?

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

    Есть 2 варианта - передавайте лямбду, которая будет захватывать this и вызывать у него метод объекта.
    Или, как показано тут, передавайте туда &Matrix::findNumberInRow c первым аргументом this.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать для нахождение уравнения поверхности по 3 точками?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Пусть точка p=(x,y,z) принадлежит плоскости. Пусть 3 точки - p1, p2, p3.

    Тогда вектор (p-p1) должен раскладываться на вектора p2-p1 и p3-p1.

    Т.е. определитель матрицы 3x3 из этих трех векторов должен быть нулевым.

    det {{x-p1x, p2x-p1x, p3x-p1x},
     {y-p1y, p2y-p1y, p3y-p1y},
     {z-p1z, p2z-p1z, p3z-p1z}} = 0


    Раскрываете определитель по первому столбцу и получаете
    A = det({{p2y-p1y, p3y-p1y}, {p2z-p1z, p3z-p1z}})
    И т.д.
    D = -p1x*A-p1y*B-p1z*C
    Ответ написан
  • Что думаете об этом решении задачи?

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

    Но, так-то там числа фиббоначи, не превышающие 4000000. Их таких дай бог 100. Там можно их все считать по несколько раз- вы разницу скорости работы скрипта не измерите никак.

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

    Заведите вы третью временную переменную и считайте через нее, чтобы в цикле всегда n было большим числом (m = 4*n+b; b=n; n=m). Или вообще воспользуйтесь фишками питона и делайте множественное присвоение:
    b, n = n, 4*n+b;
    Ответ написан
    8 комментариев
  • Как практически использовать теорему Колмогорова-Арнольда?

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

    Например, x*y*z вы в сумму никогда не разложите. Зато, если взять f(a,b) = a*b, то можно сделать f(x,f(y,z)).

    Это хорошо для оптимизации

    Эта суперпозиция не будет лучше для оптимизации ни с какой точки зрения.

    Практически это можно сделать так - расставьте все скобки рядом со всеми операциями в выражении. Каждая операция - это своя функция. Вот у вас и суперпозиция.
    Ответ написан
    Комментировать
  • Зачем Visual Studio нужен свой runtime?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Этот рантайм - это библиотеки для .Net

    Его пришлось запилить, когда MS сделал С# и .Net. Тупо копировать туда libc++ почему-то не решили.

    В C++ поддержку этого добра добавили, чтобы была совместимость и больше программистов писало на майкросовтовской технологии.

    Оно работает в c++, только если попросить visual studio компилировать под common language runtime.
    Ответ написан
    Комментировать
  • Почему создаётся бесконечный указатель в дереве?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вот этот код создает кольцевую ссылку:
    if (left) {
            tree->left = readElement(tree);
        }


    Что вы там пытаетесь сделать? Если вы хотите прочитать элемент в дерево, то ваща readElement(tree) вернет указатель на новый корень. Если выхотите добавить в левое поддерево (и грантируете, что следующий элемент будет меньше корня), то надо добавлять в tree->left а не tree.
    Ответ написан
  • В чём разница между алгоритмами операций в дополнительных и обратных кодах?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Обратный код: !x = 2^n-1 - x.
    Дополнительный код - !x+1 = 2^n - x.

    В дополнительном коде число -x записывается как 2^n-x. Поэтому его можно просто прибавлять/вычитать/умножать - лишнее 2^n не влезает в разрядность переменной и просто будет проигнорированно.

    В обратном коде у вас есть лишнее -1, которое надо компенсировать. прибавлять при вычитании, вычитать при сложении и прибавлять множитель при умножении.

    Еще, в обратном коде никак не записать 2^(n-1), потому что число 0 представимо 2 раза в виде 00000000 и 100000000.
    Ответ написан
    Комментировать