Что такое спортивное программирование и как оно работает
Об эксперте: Андрей Райгородский, доктор физико-математических наук, профессор МФТИ, Директор Финала ICPC в Москве, Директор Физтех-школы прикладной математики и информатики МФТИ.
Что такое спортивное программирование
Представьте себе коридор с бесконечным рядом запертых дверей. Если превратить их открывание в задачу с алгоритмом, у нее будет несколько решений.
Классическому, «промышленному» программисту поручат отлить лом, вскрывающий как можно больше дверей, и дешевый в производстве. А задача спортивного — понять, какая отмычка взломает все за пять минут. К слову, спортивные программисты встречаются в 70 раз реже.
Ежегодно программисты со всего мира (главным образом, студенты) встречаются на командных и индивидуальных турнирах. Самые престижные: старейший в своем роде чемпионат ICPC (International Collegiate Programming Contest), конкурс Google Code Jam, олимпиада IOI.
Конечно, замки там никто не вскрывает — обходятся математикой и написанием кода. Задания финалов в разы сложнее примера выше, а время жестко ограничено. Да и по накалу страстей ИТ-чемпионаты порой дают фору Олимпийским играм.
Особенности и практический смысл ИТ-спорта
Участникам соревнований есть за что бороться: на кону не только денежные призы, но и вакансии в крупнейших корпорациях с самыми высокими зарплатами.
От спортивных программистов требуется не только решать алгоритмические задачи, но делать это быстро и оптимально. Такие навыки даются непросто: так, подготовка к чемпионату ICPC требует регулярных тренировок по 4–5 часов, занятий с личным тренером, участия в сборах и отборочных турах.
Не следует думать, что речь о какой-то отдельной науке. Основы традиционного и спортивного программирования едины, и поначалу функция соревновательного элемента — заинтересовать подростка. Олимпиады дают мотивацию к учебе, позволяют поступать в вузы без экзаменов — а уже в вузах программисты приобретают более фундаментальные навыки. Среди них умение создавать решения не на пять минут, а на годы вперед для нужд конкретной индустрии.
Олимпиадный опыт не снижает квалификацию, но для полноценной карьеры одних спортивных навыков недостаточно. Преподаватели МФТИ уже много лет избавляют олимпиадников от их «профессионального синдрома»: заботясь только о быстродействии кода, студенты жертвуют универсальностью и прибегают к сомнительным «костылям». А в промышленных программах «костыли» недопустимы.
Говоря проще, программист должен не только «изобретать, как Тесла», но и «продавать, как Эдисон».
Что изменилось за последние годы
Программирование постепенно превращается в профессиональный спорт. Подготовка стала массовой, в отрасль пришли спонсоры: 5–10 лет назад нельзя было вообразить количества открытых сейчас кружков и курсов подготовки. Программа постоянно усложняется: скажем, финалисты 2010-х годов уже не смогут повторить свой успех. На задачах финалов прошлых лет сегодня тренируют новичков.
Как и олимпийский спорт, современные чемпионаты по программированию все сильнее походят на «битвы титанов», где счет идет на секунды. Но такое сходство — лишь следствие повышения ставок. Повышаются они потому, что за ИТ-чемпионатами пристально следят все крупнейшие компании отрасли.
Что нужно бизнесу
С каждым годом карьерные возможности в секторе растут. Но суть не в том, что ИТ-гиганты встают за медалистами в очередь, — такое «коллекционирование» чемпионов для них просто дело принципа. Когда подготовка стала доступна всем, а число олимпиадников выросло в разы, те перестали быть штучным товаром — и стали рыночным.
А значит, спортивной натасканности и медали больше недостаточно для карьеры. Бизнесу нужны не только «теслы», но и «эдисоны». И тех, и других на рынке хватает — поэтому встает вопрос «а что я умею помимо решения задач?».
И тогда судьбу специалиста решают два качества: soft skills и кругозор. Первый термин объединяет эмоциональный интеллект, умения работать в команде, адаптироваться к новым задачам. Стереотип «айтишник — значит интроверт» сильно вредит индустрии, ведь успех разработки — это успех команды и коммуникации между ее членами.
А кругозор программиста — это его способность решать стратегические задачи. Это знания продвинутой математики, логики и профильных дисциплин; это практический опыт; это понимание процессов в индустрии, где он занят, какой бы та ни была. Такой кругозор — продукт всестороннего высшего образования, и ни олимпиады, ни модные сейчас «образовательные услуги» дать его не могут.
Почему россияне так популярны?
Вот уже восемь лет подряд чемпионами ICPC становятся только российские студенты — а в 2006 году лучшие вузы мира (Кембридж, Гарвард, MIT и десятки других) обошла команда Саратовского университета. Авторитет российской программистской школы непоколебим.
Секрет ее успеха — в трех чертах российского образования: охвате, массовости и глубине.
Охват школьных программ знакомит детей с основами программирования уже в 5–6 классах — ранний старт закрепляет навыки «на подкорке». Школьники за рубежом не изучают программирование вовсе или начинают ближе к выпуску, тратя время на азы.
Массовость гарантирует постоянный приток кадров и каждый год повышает планку. Речь о тех самых кружках, университетских курсах и секциях: их число с годами только растет.
Наконец, из российских вузов выходят не просто продвинутые «кодеры», а специалисты широкого профиля. Только в нашей стране есть площадки вроде Физтех-школы ФПМИ при МФТИ, где студенты не выбирают между «спортивным» и «промышленным» программированием. Их учат всему и сразу, развивая тот самый кругозор. В результате одни и те же программисты способны и выигрывать олимпиады, и разрабатывать бизнес-решения. Неудивительно, что спрос на них огромен.
Какую карьеру строят выпускники ICPC
Принято думать, что чемпионы уходят в ИТ-гиганты едва ли не с церемоний награждения. Это не всегда так, особенно для россиян. Фундаментальные знания и опыт позволяют им преуспевать и в банках, и в стартапах, и в собственных проектах. А кто-то и вовсе становится преподавателем или тренером олимпиадного движения (в сообществе экс-участников ICPC больше 300 тыс. лучших программистов мира, многие из которых выступают менторами для молодых коллег).
Особенно же программистов-спортсменов ценят в финансовой сфере: биржевой аналитике, алгоритмической торговле, блокчейн-платформах. Именно там прорывные идеи и нестандартное мышление олимпиадников пригождаются больше всего.
Как вырастить спортивного программиста?
Главный совет: начинать как можно раньше. Лучше всего — в 11–13 лет. Если закрепить в этом возрасте все базовые термины и методы, то уже к старшим классам можно приниматься за первые конкурсы, пробовать себя на молодежных хакатонах. В идеале — посещать курсы или летние сборы от центров подготовки, подобрать толкового репетитора.
Первым испытанием часто становится олимпиада по информатике или другой конкурс, дающий право поступить в вуз без экзаменов. А в вузах процесс встает совсем на другие рельсы: на базе центров подготовки предстоит сформировать команды, приучить их к жесткому графику тренировок, назначить тренеров и восполнить недостающие знания (например, языка: все международные чемпионаты проходят только на английском).
В МФТИ таким тренировочным центром является ЦРИТО — Центр развития ИТ-образования. На базе центра проводятся регулярные тренировки и состязания. Здесь опытные тренеры готовят команды для выступлений на международных соревнованиях, в том числе ICPC.
Несмотря на все усилия специалистов, процесс подготовки к олимпиадам — личное дело каждого программиста. И ключевую роль в успехе сыграют его трудолюбие, сообразительность и умение действовать в команде.
Чек-лист: олимпиадное программирование — с чего начать школьнику?
Ведущий разработчик «Яндекса» и руководитель службы поисковых подсказок
Глеб Евстропов, ведущий разработчик «Яндекса» и руководитель службы поисковых подсказок, член жюри Всероссийской олимпиады школьников по информатике, рассказал, как начать заниматься спортивным программированием, за какие задачи браться в первую очередь и какие преимущества даёт участие в олимпиадах.
Олимпиадное или спортивное программирование — это участие в соревнованиях по решению нетривиальных алгоритмических задач. Оно позволяет получить фундаментальные знания, научиться эффективнее писать код и подготовиться к дальнейшей карьере — победителей и призеров олимпиад охотно нанимают ведущие IT-компании.
На старте
Программирование — это умение превращать объекты из реальных задач в абстрактные сущности и выражать их взаимодействие на языке программного кода. Поэтому главное условие для изучения программирования — абстрактное мышление, на которое сильно влияет уровень преподавания школьной математики.
Если вам интересно программирование, и у вас уже начало формироваться абстрактное мышление, с поддержкой увлечённого педагога довольно быстро освоите базовые знания, достаточные для участия в олимпиадах. Однако подготовиться к соревнованиям можно и самостоятельно, главное — сопровождать каждую пройденную тему, даже самую простую, усиленной практикой.
С чего начать?
Сперва нужно освоить какой-нибудь язык программирования. Например, раньше учебным языком был Pascal. Сейчас принято начинать с Python, который популярен среди тех, кто хочет быстро научиться писать код. Этот язык очень дружелюбный к начинающим, у него есть подробная и понятная документация и большое количество библиотек. Но чтобы продолжать участвовать в более сложных олимпиадах, надо будет рано или поздно овладеть C++.
Минимум тем, которые нужно изучить: переменные, операторы присваивания, логические и арифметические операции, условные операторы, потом — массивы и циклы, процедуры и функции. Для того, чтобы в них разобраться, можно, например, посмотреть курс Михаила Густокашина по C++ на Stepik. С этой базой можно решать первые олимпиадные задачи.
Как тренироваться?
Для программирования в первую очередь важна практика, хотя оно требует и теоретической подготовки. Это как водить машину: правила движения можно изучить и в классе автошколы, но научиться ездить можно только сидя за рулём автомобиля.
Я думаю, есть два основных способа выучить программирование:
Олимпиадное программирование хорошо тем, что практиковаться можно и самостоятельно, без помощи преподавателя. Есть платформы, на которых доступно большое количество олимпиадных задач. Решаешь задачу, пишешь код, отправляешь его на проверку и тут же получаешь результат. Мгновенная обратная связь мотивирует продолжать заниматься программированием.
Например, есть сайт «Информатикс», созданный коллективом московских преподавателей олимпиадной информатики. На нём есть и теоретические материалы: например, вводные лекции по Python, к которым прикреплены примеры олимпиадных задач. Прошёл тему — и сразу выполняешь по ней задание.
Самая популярная платформа для решения задач — это codeforces.com, которую создал и активно развивает Михаил Мирзаянов. На ней постоянно проводятся контесты (соревнования), открытые для всех желающих. Они рассчитаны на людей с разным уровнем: от тех, кто только вчера узнал базовые конструкции языка, до настоящих профессионалов, которые выигрывали международные соревнования и занимаются спортивным программированием уже много лет.
Путь к успеху — решать, решать, а потом ещё немного решать. Регулярно писать контесты — хотя бы один раз в неделю, а лучше два. Если решение задачи после долгих раздумий так и не нашлось, читайте её разбор.
Когда сталкиваетесь с незнакомым алгоритмом — знакомьтесь с ним, смотрите лекции на эту тему, изучайте статьи, форумы и книги. Например, «Алгоритмы: построение и анализ» Томаса Кормена и соавторов. Так выглядят дни тех, кто занимается олимпиадным программированием уже профессионально.
А ещё решать задачи гораздо приятнее и полезнее в команде. Ребята, которые занимаются в сообществе, как правило, достигают больших успехов.
Продолжение обучения
Когда человек освоил базу и знает конструкции языка, ему пора идти дальше: углубленно изучать теорию и разнообразные алгоритмы, которые позволяют по-новому работать с уже известными комбинаторными объектами. Знать алгоритмы и уметь применять сложные трюки — это хорошо, но задача никогда не состоит только из применения готовых знаний. Надо уметь сопоставлять разные параметры, вспоминать алгоритмы и модифицировать их для дальнейшего применения.
В любой задаче есть своя уникальная идея — даже если ты видел до этого тысячу других идей и задач, то 1001-я всё равно будет новой.
До многих вещей можно дойти самостоятельно, но проще и быстрее будет, если знающие люди расскажут готовые способы решения. Самый действенный путь — общаться с единомышленниками и посещать места, где делятся знаниями и опытом: выездные школы и сборы. Например, есть смена «Алгоритмы и анализ данных» в «Сириусе», где много времени уделяется тому, чтобы помочь ребятам прокачать необходимые навыки для участия в олимпиадах по информатике. Поищите и регулярные занятия, которые можно посещать круглый год: например, кружки олимпиадного программирования, которые работают в вашем городе.
Самостоятельное обучение по книгам и материалам из интернета — это длинный и сложный путь, хотя поиск самой информации и не составит труда. В частности, на сайте MAXimal собраны 145 алгоритмов для решения разных задач, а также в открытом доступе опубликованы книги по алгоритмам, оптимизации, С++ и Java.
Тактическое преимущество
Чтобы эффективно выполнять задачи, надо понимать, решение каких из них принесет наибольшую пользу в будущем.
Я подразделяю задачи на четыре уровня сложности:
На смене в «Сириусе» ребята, например, решали такие задачи:
Ошибки при подготовке к олимпиаде
Ударяться в крайности. «Я всегда дохожу до решения сам и никогда никуда не подсматриваю. Если мне нужно будет потратить три недели, чтобы решить задачу, то я потрачу три недели». До всего доходить самостоятельно — это круто, но неэффективно. К тому же, этот путь потребует слишком много силы воли, которая редко у кого встречается, а также может привести к выгоранию и утрате мотивации.
Тут же сдаваться. «Если я не понял, как решать задачу за 15 минут, то я узнаю, как она решается, прочитав её разбор». При помощи ресурса Codeforces, про который я говорил выше, можно узнать, как автор видел решение этой задачи, и как эту задачу решили бы другие люди. Но ты не дал себе шанса подумать как следует, упустил возможность найти решение самостоятельно, а это плохо для опыта и развития интуиции.
Решать только те задачи, которые нравятся. В олимпиадном программировании существуют разные типы задач: некоторые требуют в первую очередь развитого математического аппарата (например, знания теории чисел), в других идёт упор на написание кода, в-третьих — на математику (системы уравнений, теория чисел), а иногда — комбинаторику (графы). Углубляться всегда надо в те области, где возникло сопротивление. Для успеха на соревнованиях полезнее решить пять задач на нелюбимую тему, чем на ту, которая легко даётся.
Не уделять достаточно внимания коду. В процессе написания программы наброски решения переводятся на формальный язык. Иногда ты за пять минут находишь решение и потом пару часов пишешь код, а бывает и наоборот. Писать код так, чтобы в нём было меньше ошибок, способность эти ошибки находить и исправлять — навык, который можно и нужно нарабатывать. Чем больше пишешь код, тем лучше начинаешь это делать. Также полезно обсуждать с другими людьми, как писать программы с меньшим количеством ошибок и читать чужой код.
Как стать первым в спортивном программировании: Университет ИТМО делится опытом. Часть 1
В этом материале мы расскажем о новом курсе, который был запущен Университетом ИТМО на платформе edX в этом году. Под катом – рассказ о проекте «How to Win Coding Competitions: Secrets of Champions» и большое интервью с авторами и инструкторами курса, в котором они рассуждают о том, что должен знать и уметь будущий победитель, и делятся своим опытом и воспоминаниями от участия в олимпиадах по программированию.

Sebastiaan ter Burg / Flickr / CC
О курсе
Курс «Как побеждать в соревнованиях по программированию: секреты чемпионов» стартовал в октябре этого года. Авторами и инструкторами курса стали чемпионы студенческих олимпиад, в разные годы защищавшие честь Университета ИТМО: Максим Буздалов, доцент кафедры компьютерных технологий Университета ИТМО и чемпион ACM ICPC 2009 года, Павел Кротков, выпускник факультета информационных технологий и программирования Университета ИТМО, участник и организатор множества контестов по программированию в России и за рубежом, включая ACM ICPC NEERC (сейчас Павел работает в Facebook) и Дарья Яковлева, старший лаборант кафедры информационных систем Университета ИТМО, в этом году вошедшая в десятку на международном соревновании по программированию Google Code Jam for Women.
Курс рассчитан на 5 недель и направлен на изучение особенностей и подходов, использующихся в спортивном программировании. Участники узнают, как проходят соревнования, разбирают наиболее популярные подходы к решению задач и примеры их использования, тренируются решать олимпиадные задания в условиях, приближенных к реальным (финальный экзамен проходит в формате настоящего международного соревнования по программированию).
Авторы курса не просто «натаскивают» студентов на олимпиадные задачи, но и рассказывают о том, как работать в условиях жестких дедлайнов и находить необычные и эффективные решения.
Мы узнали у Максима, Павла и Дарьи, какими знаниями должен обладать будущий победитель олимпиад по программированию, насколько важны для победы «фишки» и лайфхаки и какие ошибки чаще всего допускают новички в спортивном программировании.
Программа-минимум: что необходимо знать для победы в соревновании
Павел Кротков называет основные навыки, необходимые для победы в олимпиадах: знание математики, алгоритмов, языка программирования. Без этих знаний преуспеть, самой собой, невозможно.
Вторая группа важных навыков: правильная тактика, знание «фишек». В командных соревнованиях это — умение оптимально использовать время за компьютером, разделение труда, умение отлаживать свои программы и программы сокомандников и искать в них ошибки. В личных соревнованиях к таким навыкам относятся, опять же, умение отлаживать/тестировать свои программы, быстро проверять те или иные гипотезы.
Максим Буздалов дополняет этот перечень и выделяет сразу семь навыков, необходимых для успешного участия в олимпиадах по программированию:
Придумывать решения задач научат занятия математикой. «Промышленное» программирование (то есть то, чем обычно программисты занимаются в рамках выполнения рабочих задач для бизнеса) обеспечит проработку навыков №4, №5 и №6. А вот способность эффективно реализовывать алгоритмы и структуры данных на практике и умение эффективно распределять ресурсы – это, по мнению Максима, типично «спортивные» навыки – те, которые без практики участия в соревнованиях развить крайне сложно.
Практически все эти пункты требуют постоянного развития и постоянной работы над собой. Например, если вы новичок в реализации алгоритмов, но хорошо их придумываете, вы можете решить (на бумаге) все задачи, но не решить (на компьютере) практически ни одной
Еще раз про «фишки»
Мы спросили у авторов курса, может ли новичок, разбирающийся в математике и программировании, но не знакомый с «фишками», лайфхаками и другими тайными знаниями, выиграть соревнование. Победители олимпиад согласились, что «фишки» — это еще не все: без фундаментальных знаний и трудолюбия участнику олимпиады будет обойтись гораздо сложнее:
Я бы сказал, что преуспеть в соревнованиях до определённого уровня, имея только знания из первой категории [знание математики, алгоритмов, языка программирования], можно. Тем не менее, знания из второй категории [понимание правильной тактики, навыки грамотного распределения ресурсов] сильно упрощают жизнь и работают как катализатор. Как и в любом спорте: есть физические навыки, а есть знание техники, психология, и так далее. Преуспеть только за счёт первого можно, но второе будет работать катализатором
Как мне кажется, те, кто успешны в олимпиадах (занимают призовые места на ведущих соревнованиях мира), могут быть в меру невежественными в пункте №5 [из списка выше] («хаки»), а также — при условии гениальности в остальных областях — могут не придавать значения пункту №7 (работа с ресурсами)
Дарья Яковлева отметила, что в условиях олимпиады важнее знания «фишек» может оказаться творческий подход, поэтому талантливые новички могут рассчитывать на достойный результат:
Конечно, важно знать различные методы решения задач, но нужно заметить, что жюри олимпиад старается составить задачи таким образом, чтобы участники в первую очередь придумали идею, решение самостоятельно. Однако сложные задачи, разумеется, требуют дополнительных знаний. Поэтому, я думаю, выиграть будет сложно, а попасть в топ-10 реально
Про работу в команде
Базовые умения и навыки в одиночном и командном программировании отличаются — правда, незначительно. Дарья уточняет:
В командных соревнованиях у команды есть только один компьютер. Поэтому в течение олимпиады только один человек пишет решение задачи на компьютере, остальные ребята решают другие задачи на листочках.Обычно в команде есть: математик, программист и любитель решать нестандартные задачи
Это означает, что участник командных соревнований может сделать «упор» на одной или нескольких областях – в этом случае его слабые стороны компенсируют коллеги. Максим в этой связи вспоминает турнир ACM ICPC 2009 года:
Так, например, в нашей команде (мы были чемпионами мира по программированию 2009 года) Женя Капун был непревзойденным изобретателем решений, Слава Исенбаев был отличным «универсальным бойцом», а задачи, требующие больших объемов аккуратного кода (например, задачи на вычислительную геометрию), лучше всех писал я
Максим и Павел отмечают: разделение ролей в команде часто происходит естественным путем в течение первого десятка тренировок. Бывает, что у сокомандников есть слегка различающиеся интересы, и в результате разные участники понемногу специализируются на разных направлениях (как уточняет Максим, нелегких — например, на вычислительной геометрии, задачах на потоки, «хитрых» структурах данных, суффиксных деревьях или суффиксных автоматах и так далее). Кто-то быстрее реализовывает стандартный алгоритм, или лучше ориентируется в том или ином разделе математики — все это влияет на неформальное распределение ролей в команде.
Бывают команды с ярко выраженным «математиком» и ярко выраженным «кодером». Абсолютно изолировать эти навыки, естественно, не получается, так как кодер должен понимать математика и наоборот. Кроме того, если они также участвуют и в личных соревнованиях, неравенство со временем может уменьшаться, так как участники учатся друг у друга.
В любом случае, если у вас в команде есть «математик», или «кодер», или «тестер», или специалист по суффиксным автоматам — это не означает, что вам не надо развивать соответствующие навыки. Как раз наоборот — вам есть, у кого учиться, и этим надо пользоваться
Бывает, что сокомандники оказываются примерно равны по силе и по набору навыков — в результате тактика работы в команде сводится к тому, что задачу пишет тот, кто первый ее решил. Однако, как отмечает Павел, распределение ролей не всегда связано со специализацией на той или иной области знаний: в большинстве команд есть также человек, который может принять решение в сложной ситуации — его можно назвать лидером или капитаном.
Подводные камни: на чем проваливаются неопытные участники
Как отмечают авторы курса, основные проблемы новичков связаны в первую очередь с переоценкой своих сил и возможностей. Максим Буздалов называет настоящим бичом неопытных участников их сногсшибательную уверенность в том, что код, который они написали, работает.
Причем они практически не различают [разницу между] «работает» и «работает на примере из условия». Им не приходит мысль проверить код еще раз, придумать контрпример, попробовать, наконец, доказать корректность решения. В частности, поэтому вердикт вида «Неверный ответ, тест 2» оставляет таких участников в крайней растерянности, а несколько таких вердиктов подряд — в состоянии основательной озлобленности.
В качестве примера Максим приводит одну из задач с курса «Как побеждать в соревнованиях по программированию: секреты чемпионов». Дана матрица из чисел размера 3×3, необходимо выбрать из этой матрицы три числа так, чтобы ни в одном столбце и ни в одной строке не было бы выбрано более одного числа, а корень из суммы квадратов чисел был максимален.
Однако многие участники курса присылали такое решение: сначала выберем максимальное из чисел в матрице, затем вычеркнем соответствующую строку и столбец, затем опять выберем максимум, и так далее. Приводило это к неверному ответу на шестом тесте. Это решение очень легко «убить»: достаточно рассмотреть, что произойдет на такой матрице:
Правильное решение выберет две восьмерки и оставшуюся единицу, при этом сумма квадратов будет равна 129. «Жадное» решение выберет девятку, потом ему не остается ничего, кроме единиц, и сумма квадратов составит 83. Извлечение корня, конечно же, не изменит того, что первый ответ — больше, а следовательно, лучше.
Получив подобный пример, многие участники начали писать всевозможные разборы случаев, получая неверные ответы на том же тесте или на других тестах, при этом упуская главное — получив несложный контрпример для логики работы основной части своего решения, следует остановиться и подумать. Вместо затыкания дыр, расстановки подпорок и сколачивания костылей, хорошо бы хотя бы обосновать, почему решение вообще работает. А в идеале — математически строго доказать
Еще одна распространенная ошибка, которую отмечает Дарья, — переполнение типа данных int:
Она [ошибка] случается в том случае, когда вы пытаетесь «положить» в переменную значение больше допустимого. Нужно быть внимательным и оценивать порядок ваших значений при решении задачи, и всё будет хорошо
Павел Кротков отмечает еще одну важную особенность опытных участников олимпиад — стрессоустойчивость. Ее новичкам также не хватает — именно поэтому неверное решение может легко вызвать недоумение и панику и приведет к потере драгоценного времени.
Об умении преодолеть стресс речь пойдет и во второй части нашей беседы: авторы и инструкторы курса расскажут, какую роль в процессе подготовки к соревнованию играет психология и правильный настрой, поделятся своими лайфхаками и маленькими хитростями, а также объяснят, кому (помимо будущих призеров олимпиад) может быть интересен курс «How to Win Coding Competitions: Secrets of Champions» Университета ИТМО.




