Задать вопрос
Ответы пользователя по тегу C++
  • Что не так с кодом для решения по математической игре Баше?

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

    Во-вторых, ошибка в алгоритме. Задача - проверить, что шаги оптимальные. Для этого вам надо знать оптимальный шаг и сравнивать его с текущим. Можете сформулировать оптимальную стратегию?

    Возьмите, например, k=4,5,6 и порисуйте на бумажке, попробуйте подсчитать, какие позиции выигрышные (из них можно сделать ход в проигрышную позицию), а какие - проигрышные (любой ход ведет в выигрышную позицию). Считайте увеличивая количество предметов. Позиция с 0 предментами - проигрышная - предыдущий игрок придя в нее выиграл. Позиция 1 - выигрышная, потому что можно пойти в проигрышную 0. Найдите закономерность, попытайтесь ее логически обосновать.

    Пример для k=3:

    0 - проигрышная

    1 - выигрышная ( можно взять 1)

    2 - выигрышная (можно взять 2)

    3 - выигрышная (можно взять 3)

    4 - проигрышная

    5 - выигрышная (можно попасть в 4, взяв 1)

    6 - выигрышная (можно попасть в 4, взяв 2)

    7 - выигрышная (можно взять 3 и попасть в проигрышную 4)

    8 - проигрышная (любой ход ведеть в выигрышные 5-7)

    ...
    Ответ написан
    3 комментария
  • Где собрать решение?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Есть такая штука: https://chromium.googlesource.com/infra/goma/server/

    Позволяет собирать большие проекты параллельно на куче машин. Да, эти 30 минут сборки все равно придется потратить. И никто вам бесплатно вычислительные мощности под это не даст. Придется свои сервера настраивать.

    Еще есть вариант переструктурировать ваш проект, что бы при небольших изменениях понадобилось бы собирать лишь малую часть объектников. И 2 гигабайта в одном файле - это какой-то перебор. Если вы тесты разобъете на много логически обособленных частей, то есть шанс, что сборка сильно ускорится. Да, придется запускать больше файлов, но это сделать просто.
    Ответ написан
    Комментировать
  • Как я могу использовать объект JavaScript в c++?

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

    Если же вы хотите эту конкретную (msg) структуру парсить, то возможно вам удасться превратить json в class в двумя string и одним int.
    Ответ написан
    Комментировать
  • Что здесь написано?

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

    Если итератору присвоить значение (it = 10;), то оно остается в памяти, при сдвигании итератора вперед (it++;) это значение записывается в выходной файл и следующее присвоение скормит итертору значение в следующей позиции. Этот итератор сделан, чтобы можно было писать в файл, как в C++ коллекцию (например, в вектор).

    Важно, что у этого итератора оператор * ничего не делает, возвращает сам итератор. Оператор присвоения, кстати, тоже возвращает сам итератор.

    Поэтому конструкция *(val%2 ? OddOut : EvenOut) вернет или итератор OddOut или EvenOut в зависимости от четности val. Далее, конструкция (... = val)++; запишет число val в один из выходных итераторов и сдвинет его на позицию вперед.

    Весь код выше создает 2 output_iterator, для двух заданных файлов. Потом for_each через оператор() у класса скармливает ему входные числа из cin (тут работает istream_iterator, который позволяет читать из файлов, как из вектора). А класс, пользуясь конструкцией выше, записывает числа в один из двух файлов в зависимости от четности.
    Ответ написан
    Комментировать
  • Как Вы обходитесь без "if"?

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    if (res1 = true)

    Тут вы присваиваете переменной res1 значение true и потом смотрите на ее значение в условии.

    Это вызвано тем, что оператор присврения возвращает значение переменной. Т.е. (res1 = true) == true. Если это вставить в if, то это то же самое что if(true).

    Для сравнения нужно использовать "==".

    Но, вообще говоря, if(res1 == true) - очень плохой код. Правильно писать if (res1).
    Ответ написан
    Комментировать
  • Почему не работают хеши?

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

    И xhash и gethash написаны с ошибками.

    Давайте посмотрим на xhash. Если l==r, то вернется s[l]*1. Вроде правильно. Если l+1=r, то ваша функция вернет s[l]*p^2+s[l]*p+s[r]. Вряд ли это то, чего вы хотели добиться. Или инициализация перед циклом неверная, или границы у цикла.
    Ответ написан
  • Какую структуру данных выбрать для подсчета элементов?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам нужен std::map или std::unordered_map. Самому писать структуру данных не надо.

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

    В качестве ключа используйте пару {Тип транспорта, номер маршрута}. В качестве значения - счетчик остановок.

    Еще вам нужен еще один map из тип транспорта-> std::set или std::unordered_set номеров маршрутов.

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

    Для поиска ответа пройдитесь циклом по всем элементам set из второго map - это все маршруты. Смотрите в первом map'е сколько остановок у этого маршрута и выбирайте максимум.
    Ответ написан
    2 комментария
  • Как вычислить сумму первых N элементов ряда?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам уже дана формула n-го элемента.
    В формуле, похоже, опечатка. Должно быть -1 в начале (если подставить n=0).
    Но это не особо важно, все равно первые члены ряда считаются отдельно.

    Соответственно, можно считать текущий элемент через предыдущий, как вы пытались:
    a_k = a_(k-1)*(-x)*(2k+1)/(2k-1)/(2k-1)/(2k-2)

    Только она не работает для k=1. Поэтому 2 первых члена ряда надо прибавить руками, а остальное в цикле i=2..n-1

    Т.е. R вам не нужен, и в коде должно быть:
    u = 1+3*x;
    ...
      u *= (-x)*(2i+1)/(2i-1)/(2i-1)/(2i-2);
      summa += u;


    Да, еще стоит разобрать крайние случаи, если n =0, то надо отдельно вывести 1 (или -1, если мы исправляем опечатку).
    Ответ написан
    4 комментария
  • С чем может быть связана ошибка доступа к чтению файла?

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

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

    Вы попробуйте только в одном месте путь передавать (или в конструкторе ofstream без вызоыва open() или используйте конструктор без параметров, но тогда оставьте open). И используйте string, раз уж его завели. И сделайте его const string заодно.
    Ответ написан
    Комментировать
  • Как реализовать приоритетную очередь?

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

    Надо поддерживать массив позиций по по всем айдишникам. При любом перемещении пары элементов в массиве в очереди надо обновлять этот массив позиций.

    При изменении приоретета уже не надо никакого find, потому что позиция уже будет доступна в массиве.

    При добавлении нового элемента не надо вызывать build_heap. достаточно только shift_up от нового элемента. У вас в программе отдельно этой функции нет, но она фактически реализована в decrease_key. Только нужно, опять же, проходится не по всей очереди, а только по отцам. В цикле надо делать не i--, а i = (i+1)/2-1.

    И ошибка как раз в decrease_key, У вас цикл по i, а внутри все время используется k.
    Ответ написан
    5 комментариев
  • Как побороть переполнение?

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

    У вас ошибка вот тут:
    long long div_up(int x, int y)

    Типа параметров - int. Вы когда в эту функцию передаете long long сумму - происходит переполнение.

    Просто измените типы на long long и должно пройти.
    Ответ написан
    1 комментарий
  • K-ая порядковая статистика. В чем проблема?

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

    Представьте, что у вас массив из 2 элементов и первый - больше второго (a[0] = pivot > a[1]).

    До цикла l = 0, h = 2, i = 0. Потом в первом while вы делаете i++. Потом сравниваете a[i] с pivot в первом while. a[1] < pivot по предположению, поэтому вы делаете i = 2. Все - вы уже вышли за границу массива.

    Перепишите со стандартной схемой разбиения Хоара или Ломуто.

    Или придется всякие условия i < j везде дописывать, но я не уверен.
    Ответ написан
    2 комментария
  • Как посчитать количество инверсий, используя сортировку слиянием?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вроде все правильно. Какие ограничения? Может быть переполнение, ведь максимальный ответ n(n-1)/2. Для переполнения int достаточно 65536 чисел в массиве.
    Ответ написан
    4 комментария
  • Как перебрать все возможные комбинации символов?

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

    Нужно или писать рекурсивную функцию, или итеративно дописывать ко всем элементам массива по одному элементу из сделеющего множества. Просто переведите этот код на с++.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    При копировании назад из временного массива b в массив a у вас индексация с ошибкой. Хоть b индексируется с 0, вы обращаетесь к элементам начиная с s.
    Ответ написан
    1 комментарий
  • Почему в данной ситуации map быстрее unordered_map?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    unordered_map может работать за линию в худшем случае. Это если происходит много коллизий. Стандартная реализация еще и дико медленная, через связные списки работает и часто использует тривиальные хеши (буквально, значение int берется за значение хеша). Подобрать смертельный тест для такого хэша совсем не сложно. Введите вашей программе на вход координаты деревьев i*8192 - если я правильно понимаю, unordered_map будет работать ооочень долго.

    Можно избавиться от таких тривиальных коллизий, если реализовать свою хеш функцию. А там можно хоть (x * 239017l) % (1<<31) возвращать. И то, лучше будет.

    Еще, чтобы избавиться от постоянных рехешированний можно добавить вот это:
    len.reserve(1048576);
    len.max_load_factor(0.25);


    Говорят, что если заранее зарезервировать место и указать load_factor поменьше, то unordered_map будет раз в 10 быстрее.

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

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

    Так, 323 в десятичной системе, если перевести в 16-ричную будет:
    323 = 16*20+3. Остаток 3, результат 20.
    20 = 16*1+4. Остаток 4, результат 1
    1 = 16*0+1. Остаток 1. результат 0.

    Отсюда получается, что искомое число в 16-ричной системе 143. Проверка 16*16*1+16*4+3 = 256+64+3=323

    Итак, вам надо сделать то же самое, но не в 10-чиной системе, а в k-ичной (ведь переводим не из 10-чной а из k-ичной). Число записано в виде k-ичных цифр в массиве. Это, фактически, длинная арифметика с базой k.

    Для этого надо реализовать деление числа в виде массива цифр на короткое с остатком.
    Это делается со старших разрядов к младшим. Тупо делите каждую цифру с остатком отдельно. Остаток переносите в младший разряд. Последний остаток - это остаток от всего деления. Результаты делений - новые цифры.

    Удобнее хранить цифры от младших к старшим в массиве. Т.е. элемент массива 0 - это единицы. Элемент 1 - это первая степень k. Еще стоит хранить номер последней ненулевой цифры. Смотрите реализацию по ссылке выше.

    Вот пример из условия. Пусть k=666, t=10, число - {2, 179, 113} (в условии цифры от старших к младшим, но мы храним наоборот).

    Делим на 10.

    113/10 = 11 + остаток 3. Переносим 3 в младший разряд (умножив на 666), получаем 3*666+179=2177.
    2177 / 10 = 217 + остаток 7. 7*666+2 = 4664.
    4664 /10 = 466 + остаток 4. Дальше разрядов нет, значит 4 и есть остаток от деления {2, 179, 113} на 10. Результат деления - {466, 217, 11}

    Последний остаток - 4 - это и есть младшая цифра в ответе (он в условии написан - 50241044). Надо продолжать делить результат пока он не окажется 0.

    Повторим для {466, 217, 11}:
    11/10 = 1 + остаток 1. 1*666+217 = 883
    883/10 = 88 + остаток 3. 3*666+446 = 2444
    2444/10 = 244 + остаток 4.
    Опять, последний остаток - это остаток всего деления и следующая цифра в ответе (опять 4).
    Результаты деления - {244, 88, 1}

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

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

    Можно проверить в 2 этапа. Подсчитать A=a*x+b, B=c*x+d. Потом проверить что A*x*x = -B. Но тут нужно заранее отсечь случаи, когда abs(A) > abs(B)/(x*x). Тогда переполнений не будет.

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

    if (d != 0) {
      n = d;
    } else {
      s.push_back(0);
      if (c != 0) {
        n = c;
      } else if (b != 0) {
       n = b;
      } else {
       n = a;
      }
    }
    if (n == 0) {cout << "-1"; return}
    Ответ написан
    2 комментария