Задать вопрос
  • Как сгенеририовать СЛАУ (система линейных алгебраических уравнений) больших размеров?

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

    В C++ есть генератор случайных чисел - функция rand(). Гуглите ее, она вернет случайное целое число. Если вам нужны вещественные и возможно отрицательные коэффициенты, то эти целые числа можно использовать для получения вещественных. Гуглите "C++ случайное вещественное число".
    Ответ написан
  • Сколькими ходами кубик Рубика возвращается в изначальное положение?

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Так или иначе придется считать количество операций. Иногда это просто, когда там тупо вложенные циклы с фиксированным количеством итераций. Иногда придется пораскинуть мозгами. Например, можно понять сколько уровней будет у рекурсивного вызова и как много операций на каждом уровне происходит. Логарифмы обычно вылезают от деления данных пополам. Когда просят сделать что-то быстрее то надо подумать а нельзя ли тут применить какую-то структуру данных. Например, можно ли BST заменить хеш таблицей.
    Ответ написан
    Комментировать
  • Как решить задачу по комбинаторике?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вам нужна формула размещений. От использованной формулы сочетаний отличается отсутствием k! в знаменателе.
    Ответ написан
    Комментировать
  • Как инициализировать n так что бы оно работало для всех введенных n,а не только для 2?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Между вводом и проверкой в if-e надо поставить логическую операцию или (||).
    Ответ написан
  • В чем логическая ошибка сигсегва?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Проблема в том, что "214" - это строковая константа. Поэтому char *num = "214"; инициализурует указатель num адресом этой константы. Сама эта константа, видимо, лежит в read only памяти. Поэтому когда вы в алгоритме попытаетесь что-то в массив записать, программа упадет.

    Если вы внимательно почитаете вывод компилятора (желательно с ключем "-Wall"), то он вам про это выдаст варнинг:
    main.cpp:54:17: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]


    Надо делать так:
    char num[] = "214";

    Ну еще у вас там в коде ошибка с непроставленным где надо +1 у index. Разворачивать надо кусок правее только что увеличенного элемента. А вы разворачиваете вместе с ним. Поэтому ваша программа еще и повиснет.

    Ну и первую перестановку ваш код не выводит.

    И последнее, вместо for (; index != -1;) лучше использовать while (index != -1)
    Ответ написан
    2 комментария
  • Как проверить n-количество или они образуют последовательность Фибоначчи?

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

    Если какая-то проверка где-то не сошлась - надо вывести нет. Иначе, надо вывести да.

    Удобно это делать в виде функции возвращающей булевое значение. Тогда в конце ее пишите return true. А внутри каждая проверка возвращает false, если она провалилась.
    Ответ написан
    Комментировать
  • Как найти общую формулу?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    По идее надо бы задать формулу кусочно для разных n, но можно все собрать в одну формулу как-то так:
    (2-n)(3-n)/2*f1(n) + (n-1)(3-n)*f2(n) + (n-1)(n-2)/2*f3(n)


    Далее f1(n) = b-a+1

    Для нахождения f2 и f3 можно сдвинуть левую границу вправо до первого числа нужной четности, а правую границу - влево. Потом уже зная, что 2 крайних числа в промежутке между a' и b' берутся, то фромула будет (b'-a')/2+1.

    Для такого сдвига надо будет смотреть на четность a и b и четность n.

    В итоге:
    f2(n) = ((b-b%2)-(a+a%2))/2+1
    f3(n) = ((b-1+b%2)-(a+1-a%2))/2+1

    Можно f2 и f3 объединить используя n%2 и операцию xor: если четность a или b не такая же как у n, то надо границу сдвигать (вычесть/прибваить 1). Иначе надо вычесть/прибавить 0. xor как раз равен 1 при неравнестве и 0 при совпадении четностей.

    f23(n) = ((a+(a%2 ^ n%2))-(b-(b%2)^(n%2)))/2+1

    Итоговая формула:
    (2-n)(3-n)/2*(b-a+1) + ((n-1)(3-n) + (n-1)(n-2)/2)*(((a+(a%2 ^ n%2))-(b-(b%2)^(n%2)))/2+1)


    А еще, если пользоваться битовыми функциями, то можно вместо (n-1)(3-n) + (n-1)(n-2)/2 использовать (n & 2)/2, в вместо первой скобки (1 - (n & 2)/2)

    Формула правильно возвращает 0, если чисел в промежутке нет. Правда, она не работает, если a > b.
    Ответ написан
    Комментировать
  • Как вернуть первые N максимальных элементов из массива без сортировки массива?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Есть такой алгоритм. Называется quickSelect. Фактически, это обрезанный quickSort, где после выбора ведущего элемента и разбивки массива работа продолжается только в той половине, где находится раздел между первыми K элементами и остальными N-K.

    Пусть у вас N элементов в массиве и надо вернуть K минимальных. Тогда сортировка будет работать за O(N log N), а quickselect за O(N) в среднем*. В худшем случае может быть и квадратичное время работы, но этот случай практически невозможен, если реализация испольует случайные числа для выбора ведущего элемента.

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

    Суть его в том, чтобы в куче (heap aka priority queue) поддерживать пока найденные K минимальных элементов. При этом куча будет на максимум. Сначала туда кладутся первые k элементов массива, а потом каждый следующий вытесняет максимальный элемент в куче, если он его меньше.

    * Вообще говоря, можно заставить quickselect и quicksort работать идеально всегда, если использовать алгоритм Блюма-Флойда-Пратта-Ривеста-Тарьяна, который ищет медиану за O(n). Но на практике этот алгоритм не применятеся, потому что у него такая константа, что там на логарифм хватит и еще на квадрат останется.
    Ответ написан
    2 комментария
  • Как в проходе графа DFS создать массив маршурутов до нужной вершины?

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

    При выходе из функции очищайте пометку visited. При входе добавляйте вершину в массив/стек/список. Там будет храниться пройденный путь. При выходе из функции - убирайте последнюю вершину из пути. Если зашли в конечную вершину - выводите этот стек с вершинами.

    Еще проблемы - visited и массив пути должны быть одни на все рекурсивные вызовы. Или они должны быть глобальными или передавайте их по ссылке рекурсивно.
    Ответ написан
    2 комментария
  • Сработает ли деструктор, присвоив atomic?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Не совсем понятно, а чего вы вообще пытаетесь добиться зануляя value? После деструктора весь объект и его член value уничтожаются. Любое обращение к ним - это UB. Соотвтественно вы этот новый 0 никак снаружи пощупать не сможете.

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

    Единственный способ бороться с этим, кажется, это использовать умные указатели. Всякие WeakPtr, которые не уничтожают блок счетчиков при удалении объекта. Если же вы опустились до сырых указателей, то это тупо адрес (число). И просто по нему никак не понять, а что по этому адресу лежит - оригинальный объект или что-то левое.
    Ответ написан
  • Не работает "cin" в С++. Как исправить?

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

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

    Например браузер. Лично мне приходилось в хромиуме писать и динамическое программирование и дихотомию и всякие хитрые структуры данных.

    Из вашего списка скорее подходят бакенд и desktop. Еще очень алгоритмоемкая область - разработка игр. Вот там нужно много чего использовать, потому что надо все делать эффективно, иначе игра будет тормозить.

    По поводу второго вопроса, похоже большинство разработчиков алгоритмы презирают. Считают что это не нужно знать вообще и очень ненавидят алгоритмические интервью в ФААНГах и им подражающим.
    Ответ написан
    5 комментариев
  • Как запрограммировать построение мультипликативной группы по неприводимому многочлену?

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

    А дальше, чтобы найти мультипликативную группу, придется делать полный перебор. Перебирайте все полиномы (они у вас, видимо, над полем по модулю 2, их 2^n. Можно их перебирать как биты у целого числа). Потом умножайте на текущий полином в цикле, помечая в массиве уже полученные ранее полиномы. Если получили все 2^n элементов - вы нашли нужную группу. Если наткнулись на уже ранее полученный полином раньше времени - текущий кандидат не подходит.
    Ответ написан
    Комментировать
  • Будет ли большой std::vector быстрее, чем std::vectorstd::vector?

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

    в vector<vector> это фактически указатель на массив указателей. Строки раскиданны по памяти как попало и при обращении к ячейке будет лишнее обращение к памяти, чтобы получить адрес строки.

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

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Если есть какой-то уникальный id у заказа, и они равномерно и плотно растут (например, имеют порядковые номера), то можно смотреть на последнюю цифру. 0-2 отдавать фирме с 30% заказов, 3-9 - второй фирме. Или для равномерности отдавать второй фирме цифры 1,3,4,6,7,8,0 Если таких номеров нет, то можно генерировать случайное число для заказа и смотреть на последнюю цифру там. В среднем будет соотношение 30/70 примерно.
    Ответ написан
    Комментировать
  • Как добавить элемент из файла в ветвящееся дерево?

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

    Сначала читаете первую строку и создаете из нее корень дерева.

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

    В вашем примере.

    Прочитали иван, сделали корень дерева. Вектор будет {"иван"} (указатель на вершину-корень дерева).

    Прочитали алексей. 1 проблел - все хорошо, в векторое 1 элемент, значит может быть до 1 пробела. Добавили "алексей" к вершине "иван". Вектор {"иван", "алексей"}

    Прочитали игорь. Вектор стал {"иван", "алексей", "игорь"}.

    Прочитали андрей. 1 пробел. Может быть до трех пробелов, ведь в векторе 3 элемента. Добавили "андрей" к узлу из вектора по индексу 0 (-1 к количеству пробелов). обрезали вектор до длины 1 и добавили туда новую вершину. Вектор стал {"иван", "андрей"}

    И т.д.

    Для добавления вершины создайте новый TreeNode с нужной строкой и push_back в список детей для нужного отца.
    Ответ написан
    Комментировать
  • Существует ли такой алгорим?

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

    Есть такой алгоритм. В общем случае он выглядит так:

    Read(a);
    Read(b);
    DoSomething(a, b);
    Write(a+b);


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

    Поэтому 100% существует такой DoSomething, про который формально доказать что он не виснет нельзя. Иначе бы проблема остановки решалась.
    Ответ написан
    4 комментария
  • Суть макросов в с++?

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

    Еще макросы можно использовать для гарантирования инлайнинга кода. Если есть что-то часто повторяющееся, например, это же самое логирование, то можно сделать макросы и избегать дополнительных накладных расходов на вызовы функций.
    Ответ написан
    3 комментария
  • Задача на codeforces на проходит по времени?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    У вас решение за O(NM), когда как есть решение за O(N+M).

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