Задать вопрос
Ответы пользователя по тегу Программирование
  • Где ошибка в доказательстве?

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

    Правильное доказательство весьма простое и без индукции. Общее время будет
    Max(sum{i-начальнику}(bi), max{i - подчиненным}(ai))
    .
    Отсюда видно, что если вы какую-то задачу дали подчиненному, то все задачи с меньшим A нет смысла давать начальнику. Ведь второе слагаемое-максимум от этого не изменится, но первое увеличится. Можно "бесплатно" выполнить эти задачи подчиненными. Поэтому в оптимальном ответе вы даете какое-то множетсво минимальных A подчиненым, а остальные начальнику. Иначе можно какие-то задачи перекинуть с начальника на подчиненного и уменьшить первое слагаемое не меняя второе, уменьшив таким образом ответ, т.е. в этом случае решение точно не оптимальное.
    Чтобы все варианты возможных оптимумов перебрать надо отсортировать задачи по возрастанию A. Это код и делает. поддерживается сумма B у всех оставшихся задач, а от текущей берется A - который и будет максимумом для всех задач с меньшим A.
    Ответ написан
    Комментировать
  • Как доказать что мы действительно не пропустим такую пару i,j которая дает правильный ответ в методе двух указателей?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    В такой реализации это плохо видно, но можно переписать основной цикл так:
    j = Len(B)-1
    for i in range(len(A)):
      while j >= 0 and A[i] + B[j] > c:
        --j;
      if A[i] + B[j] == c:
        found = True
        break


    В этом случае после цикла while поддерживается инвариант, что a[i]+b[j] <= c и это максимальное такое j.
    Ведь, если этот инвариант поддерживался для пердыдущей итерации, то у нас было a[i-1] +b[j] <=c и a[i-1]+b[j+1]>c. Отсюда получается, a[i]+b[j+1] >= a[i-1]+b[j+1] > c. Т.е. если мы уменьшим j в цикле while инвариант останется действовать - это будет самое большое j, т.ч. a[i]+b[j] <= c.

    А этот инвариант гарантирует, что когда в цикле по i переберется значение из ответа, j гарантированно будет указываать на j из ответа. Потому что, если существуют i', j', т.ч. a[i']+b[j'] = c, то можно увеличить j' пока b там не меняется, т.ч. b[j']>b[j'], отсюда получается a[i']+b[j'] <=c и a[i']+b[j+1] > c - а это и есть наш инвариант. Т.е. на итерации i=i' найдется именно j=j'.
    Ответ написан
    3 комментария
  • В чём смысл равного ограничения времени для разных ЯП в спортивном//олимпиадном программировании?

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

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

    Edit: ах да, они этот список еще меняют иногда. Так что вполне возможно, что вы эту задачу когда-то раньше уже даже решили, но теперь она стала платной.
    Ответ написан
    Комментировать
  • Почему на leetcode различается скорость одного и того же кода?

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

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

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

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Завист от того, как реализованы "действия" в каждом окне-игре.
    Если дело на windows, то есть шанс, что окно воспримет за клик получение сообщение WM_MOUSEDOWN/WM_MOUSEUP. Тогда можно просто посылать сообщения в каждое окно параллельно отдельной программой.
    Но для некоторых игр важно, чтобы окно было активно, а некоторые еще и детектируют кучу всего с мышью и надо именно что эмулировать движение мышью через mouse_event, например. Но, в этом случае мышь одна на оба окна, поэтому надо, чтобы оба "скрипта" посылали клики централизовано, через какой-то компонент с мьютексом, который бы вы полнял ровно одно действие в единицу времени.

    Нажатия на клавиатуру обычно срабатывают просто через посылание сообщений окну, т.ч. тут все легко параллелизуется.

    Нужные функции посылания сообщения и клика мышью - это winapi, но у него, по-моему, есть и обертка даже на питоне в модуле win32 и pyautogui.
    Ответ написан
    Комментировать
  • Ошибка unterminated string literal?

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Это называется IPC (inter-process communication). Гуглите IPC + ваш язык программирования, что-то да найдете. Полно библиотек готовых. Есть способы по-производительнее сокетов (всякие отображаемые в память файлы, например), но велосипед тут переизобретать смысла нет, если это только не задание на курсе по программированию.

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

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

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

    Погуглите - есть котовые модели с инструкциями. Потом придется поэксперементировать с запросами, чтобы подобрать слова для вашего стиля. Возможно придется потом кортинку обработать в каком-нибудь графическом редакторе, чтобы заменить белый фон на прозрачный.
    Ответ написан
    Комментировать
  • Хештаблицы, можно ли мешать open addressing и chaining(решено)?

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Выведите 6^2, 66^2 и так далее. N до 20 хотя бы. Посмотрите на числа. Можете ли вы угадать цифру на заданной позиции без подсчета всего числа?

    Подсказка, вы получите вот такие вот числа:
    36
    4356
    443556
    44435556
    4444355556
    444443555556
    44444435555556
    4444444355555556
    444444443555555556
    44444444435555555556
    4444444444355555555556
    444444444443555555555556
    44444444444435555555555556
    4444444444444355555555555556
    444444444444443555555555555556
    44444444444444435555555555555556
    4444444444444444355555555555555556
    444444444444444443555555555555555556
    44444444444444444435555555555555555556
    4444444444444444444355555555555555555556


    Этот паттерн можно и доказать. Надо лишь представить возводимое в квадрат число как (10**n-1)2/3 и применить чуть-чуть элементарной алгебры, вроде формулы квадрата разности.
    Ответ написан
    Комментировать
  • Как правильно рассчитать коэффициент полезного использования пространства?

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

    Можно ускорить алгоритм сжатием координат: вввпишите все x и y координаты всех углов блоков, отсортируйте и унифицируйте (отдельно по каждой оси). Потом замените все координаты в блоках на порядковый номер в массиве уникальных координат. Примените алгоритм выше, но в конце надо помнить, что каждая ячейка теперь не 1x1, а сколько-то больше по вертикали и горизонтали.
    Ответ написан
  • Как сделать логику распространения файла?

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

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

    - определять переполнение и как-то его бросать исключение или завершать программу. Все операции идут с проверками.

    - Clamped типы. Максимальное значение типа считается бесконечностью. Прибавление к нему не меняет это значение. Переполнение выдаст это максимальное. Все операции с переменной, естественно, тоже сопровождаются проверками. Тут есть возможность потом какие-то выводы о значении счетчика потом даже делать. Вы будете видеть, что там больше или равно INT_MAX, но насколько больше - знать не будете.

    - Wraparound. Часто вам не важно абсолютное значение счетчика. Нужно лишь знать, какое из двух значений больше. При этом вы знаете, что сравниваемые значения не могут быть слишком большими. Тогда очень маленькое значение будет считаться больше очень большого. Два примерно одинаковых будут сравниваться как обычные числа. Так можно делать, например, с sequence number пакетов. Если вы получите пакет с номером 0x02 после покета с номером OxFFF1, Можно с спокойно считать, что это номер после переполнения. Ну не будет сеть задерживать перетасовывать 65 тысяч пакетов.
    Ответ написан
    1 комментарий
  • Почему мой код не проходит по времени?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас не самое эффективное решение. Что-то типа O(n sqrt(n)), когда как задачу можно решить за O(n).

    Сначала решетом эратосфена найдите для каждого числа минимальный простой делитель. У меня даже статья про этот алгоритм есть с кодом и объяснением.

    Потом, решение за O(n log n) - можно быстро найти все простые множители каждого числа используя массив с предущего шага. Считайте степени простых множителей и перемножайте их +1. Так 2^2*3^1 имеет (2+1)(1+1) = 3*2 = 6 делителей (включая 1 и 12. Если они не нужны, вычтите 1-2 в конце).

    Но можно сделать еще быстрее. Фактически применив динамическое программирование. Во втором массиве посчитайте степень минимального простого делителя для каждого числа. Если мнимальный делитель (p[i]) для i равен мнимальному для i/p[i], то степень для i будет 1 + степень для i/p[i]. Иначе она будет 1. Так же посчитайте для каждого числа что там останется, если выкинуть все вхождения минимального делителя. Потом в другом массиве посчитайте для каждого числа количество делителей - это ответ для числа без всех вхождений минимального, умноженный на количество этих минимальных делителей +1. Ну а потом по этому массиву считайте сумму. Это будет работать за O(n).
    Ответ написан
  • Как находить лучший способ решение задачи на олимпиадном программировании?

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

    А так - на до сначала построить математическую модель задачи. Понять, на что эта модель похожа. Может, тут граф нарисовать можно? Какие алгоритмы на графы вы вообще знаете? Применимы ли они тут? Или это строка. Какие есть алгоритмы на строки? Смотрите еще ограничения. По ним обчно понятно, что тут нужно что-то за O(n), или за O(n log n) написать. Множество применымых алгоритмов еще больше уменьшается.

    В задачах на оптимальность чего-то помогает рассуждение "рассмотрим ответ. Какие у него можно заметить свойства. Можно ли какой-то ответ немного поменять, не ухудшая его?" Так вы получите какое-то свойство, которое можно уже применять для построения ответа. Например в задачах на жадность так можно понять, что надо отсрортировать что-то.

    Потом, очень частая тема - ДП. Попробуйте параметризировать задачу. Свести ее к подзадачам. Формализуйте ДП (считаем вот такую вот функцию от вот этих вот параметров вот с таким вот физическим смыслом).
    Ответ написан
    Комментировать
  • Какие темы самые важные для олимпиадного программировании в книге Кормена «Алгоритмы. Построение и анализ»?

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

    Менее важные, но встречающиеся темы:
    Глава 30. Полиномы и быстрое преобразование Фурье
    Глава 31. Теоретико-числовые алгоритмы
    Глава 32. Поиск подстрок
    Глава 33. Вычислительная геометрия

    Но лучше прочитать, таки, всю книгу. Вправляет мозги, учит строить математические модели задач, что в олимпиадах очень важно.
    Ответ написан
    6 комментариев