Thursday, July 9, 2009

KPI Open 2009

Как известно, международная открытая студенческая олимпиада по программированию им. С.А. Лебедева и В.М. Глушкова, или попросту KPI Open, - это мероприятие с наибольшим в Украине бюджетом среди всех олимпиадных баталий. С сожалением должен признать, что оно в то же время славится и как самое курьозное. В прошлые годы туры не обходились как без технических проблем, так и без ошибок в тестах или проверяющих программах. Тем не менее, эти факторы не становились решающими, и победители определялись более или менее справедливо.

Вот на эту самую олимпиаду нам и предстояло отправиться. Под "нами" подразумевается тренер Темури Заркуа и две команды по два человека: Tbilisi SU 1 в составе Леквы и меня, и Tbilisi SU 2 - в составе Гиоргия Сагинадзе и Акаки Мамагеишвили.

Прилетели мы за день до регистрации. Как обычно, Киев радует глаз в первую очередь обилием полураздетых красавиц, что сразу поднимает настроение. Настроение взлетело ещё выше, когда мои опасения не оправдались и вместо общежития с туалетом в другом конце коридора и душем на этаж ниже, мы оказались в профилактории, где все вышеупомянутые прелести жизни находятся в номере. Не меняя темы, мы собрались и ушли на пляж. В Киеве мы уже бывали, но почему-то на берег Днепра никогда не выходили. Чтож, всё бывает в первый раз © Ёлка

На пляже радости наших глаз уже не было предела. Воодушевлённый увиденным, Акаки, который по-русски говорит почти как я на китайском, решил выучить пару фраз и, естественно, обратился ко мне. Недолго думая, я предложил ему знакомиться с девушками фразой "Здравствуйте. Как к Вам можно обращаться?". Ну это шутка такая была. Но Акаки моего юмора не оценил и вот так и ходил по пляжу и обращался. Успешно по ходу :)


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



Далее в программе следовало само соревнование. KPI Open проводится в два тура: первый, отборочный, состоит из 4 задач на 4 часа. На втором, основном, предлагается 6 задач и 6 часов на их решение. Рейтинговая система на этой олимпиаде уникальная и совмещает в себе ACM, topcoder и школьные олимпиады. Спросить меня, так ничего в подобной смеси хорошего нет, но на вкус и цвет... Так или иначе, за решение по каждой задаче команда награждается неким количеством очков в зависимости от "веса" этой задачи, заранее определяемого компетентной командой судей, времени, потраченного на её решение и количества пройденных тестов.

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

Так вот, первый тур. Самую лёгкую задачу, а вернее - задачу с наименьшим весом, на которую отводили 15 минут, никто не успел сдать даже за 20. Зато с той, которая была оценена в 45 минут, много команд расправилось быстрее, чем за десять. Ну это-то ладно, главное, что, как выразился позднее кто-то на закрытии, "задачи каждый год новые и оригинальные". На эти задачи вы сможете посмотреть, если их когда-нибудь выложат на сайте олимпиады. А до тех пор можете взглянуть на две задачи, похожие на предложенные на туре как две капли воды: Decoding Task и Amusing Numbers. По какому-то чудовищному совпадению, организационный комитет KPI умудрился не только заново изобрести такие же задачи, но и повторить текст условия слово в слово на разных языках. А если всё же преположить - чисто гипотетически [
© "Enemy of the State"] - что это именно те задачи, то особо весёлым может показаться пункт в правилах по поводу подачи аппеляций: "Поводом для подачи аппеляции может быть неточность перевода условий задач на русский и английский языки".

Во втором раунде невероятных совпадений уже не наблюдалось, а может, их просто не успели заметить, потому что примерно на 100-ой минуте соревнования произошел невероятный сбой сервера. В течение трех часов производились не особо успешные попытки его реанимировать. В это время участники олимпиады из нашей комнаты (Леква и я в первую очередь) успели нарушить практически все правила олимпиады: звонили, слушали музыку, спали на приставленных друг к другу стульях, выходили наружу. Все команды пообщались между собой и с заглядывавшими иногда тренерами. Когда мы собрались пойти за пивом, в класс зашел дядька из оргкомитета и с прискорбным видом объявил трагическую весть: организаторами было принято решение о прекращении тура. После этого в течение пары часов тренерами и представителями оргкомитета обсуждались возможные варианты развития событий, и в итоге было решено аннулировать результаты неоконченного второго тура и объявить победителей на основе первого. Не знаю, лучшее ли это было решение, но в создавшейся ситуации вообще не видно было нормального выхода. Так что вот так выглядят окончательные результаты.


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



Ну что ж, а потом мы улетели домой, но обещали обязательно вернуться :)

SRM 443

Примерно в начале апреля был объявлен конкурс на составление задач для onsite-раунда TCO 2009 - ежегодного чемпионата, проводимого топкодером. Вплоть до начала мая авторы могли засылать свои задачи, из которых должны были выбрать лучшие 12. Потом в течение мая их тестили и отбирали лучшие шесть - 3 для полуфинала и 3 для финала.

Я тоже решил испытать судьбу и предложил пару задач - один Easy и один Medium. В итоге в 12 кандидатов ни одна не попала. Во время моего второго SRMа я пообщался с Иваном по их поводу, и он сказал, что Easy была слишком сложной, а Medium - слишком лёгкой :) Тем не менее, он считал, что первую можно использовать как Div1 Medium для обычного матча, а вторую - как Div2 Hard. Так что я вскоре состряпал ещё 3 задачи и попросил на них взглянуть.

Сразу после окончания TCO, то есть в первых числах июня, Иван действительно посмотрел на задачи. Более того, он сразу предложил мне выбрать дату матча - честно говоря, проведя SRM только за месяц до этого, я этого не ожидал. На календаре значился только SRM 443, а остальные ещё не были прописаны, поэтому особо выбирать мне не пришлось.

В процессе тестирования я пару раз заменил Div2 Easy, а также придумал другой Div1 Hard. Наконец задачи были утверждены в том комплекте, который и попал на матч. Но вот по поводу распределения очков за задачи довольно долго шел спор. Вернее, главным образом спорили по поводу задачи BinaryFlips - той, что я задумывал как Easy для TCO. Мне она представлялась не такой уж сложной, и я требовал за неё чуть ли не 450 очков. Тестер и Метельский же, напротив, настаивали на 600. В итоге я сдался, и результаты ясно показывают, что я был неправ.

Что касается решений, в каком-то виде они лежат в editorialе на топкодере, но я всё же опишу свои варианты.

Div2 Easy - SoccerLeagues. Как и подобает задаче этого уровня, никаких особых знаний или оригинальных подходов в ней не требуется. На самом деле задача была даже легче обычного: правильно написать два вложенных цикла умудрились почти все участники.

Div2 Medium / Div1 Easy - CirclesCountry. Тут я ещё в условии прикольнулся, правда без знания грузинского языка этого всё равно не понять. Так вот, к этой задаче есть два подхода. Первый, более сложный - построить граф (а собственно дерево) из окружностей и найти в нём длину пути между окружностями, содержащими требуемые точки. Честно говоря, моё решение было именно таким, и я был довольно удивлён, когда в процессе тестирования нашлось намного более лёгкое: просто посчитать количество окружностей, которые содержат ровно одну из требуемых точек. Таким образом, для многих опытных участников проблемой стало то, что они сразу начали реализацию первого подхода и потеряли минут десять относительно людей, имплементировавших подоход №2.

Div2 Hard - Polygons2. Учитывая, что многие кодеры во втором дивизионе справились с первыми двумя задачами за 20-25 минут, по этой задаче было много (92) submission-ов. Тем не менее, большинство из них было просто перебором. В итоге правильными было только 5 решений, и самое быстрое из них заняло 42 с лишним минуты. Это меня хоть немного успокоило, потому что для меня задача была совсем не лёгкой. А решать её надо с помощью динамического программирования: ответ можно легко вычислить, если знать, сколькими способами можно получить (K-1)-угольник с наибольшей стороной длины A и периметром P. Эту начальную идею нужно было несколько оптимизировать, но в итоге код получался длиной в несколько строк.

Div1 Medium - BinaryFlips. В отличии от подходов, описанных на топкодере, моё решение имеет сложность O(1). Я бы его и туда добавил, но боюсь, что не смогу нормально объяснить. По крайней мере, пока здесь попытаюсь.
Давайте каким-либо образом проиндексируем все A+B чисел. В конечном итоге нам нужно изменить ровно A индексов по отношению к их начальному состоянию. Очевидно, что за один ход мы можем изменить
ровно K индексов. За два же хода можно изменить любое четное количество индексов в пределах от 2 до 2*min(K,N-K). Например, чтобы изменить ровно 2 индекса за 2 хода (при K>1), мы можем флипануть за первый ход некоторое множество индексов {i1,i2,...,i(K-1),j1}, а за второй - множество {i1,i2,...,i(K-1),j2}. Таким образом, относительно начального положения изменятся только индексы j1 и j2. Аналогично, для изменения большего количества индексов, надо брать меньше общих элементов для изменяемых на каждом ходе множеств. Именно поэтому невозможно изменить больше, чем 2*(N-K) индексов.
Так что мы имеем? Мы должны выразить число A в виде суммы чисел K и четных чисел между 2 и 2*min(K,N-K), причём цена числа K равна 1, цена остальных чисел равна 2, и сумма должна быть как можно дешевле. Вот тут уже надо рассмотреть несколько случаев:
1) A=0 => ANS=0
2) A=K => ANS=1
3) Если ни одно не выполняется, то K>=N => ANS=-1
4) (A%2=1) AND (K%2=0) => ANS=-1. В этом случае мы пытаемся получить нечётное число суммой четных.
Обозначим теперь Z=2*min(K,N-K) и функцию ceil(X)=наименьшее целое, большее или равное X.
5) (A%2=1) AND (K%2=1) => ANS=1+2*ceil(abs(A-K)/Z).
6) (A%2=0) AND (K%2=1) => ANS=2*ceil(A/Z).
7) (A%2=0) AND (K%2=0) =>
min(1+2*ceil(abs(A-K)/Z), 2*ceil(A/Z)).
Вдумавшись в каждое из этих выражений, можно (я надеюсь) понять, какая логика за ним стоит. Правда, написав всё это, я уже не думаю, что задача была такая уж и лёгкая :D

Div1 Hard - ShuffledPlaylist. Я снова написал задачу про музыку, правда, много наврал - никогда я ничего не shuffle-ю. Так или иначе, задачу можно было решать двумя методами. Для обоих общей частью является построение матрицы переходов из одного положения в другое. Положением в задаче описывается, песня какого стиля в данный момент проигрывается и сколько минут осталось до её окончания, плюс желательно иметь одно положение для начального момента.
Более сложный метод на этом останавливается и далее работает следующим образом. Если возвести начальную матрицу в степень X и посчитать сумму элементов, обозначающих переход от начального положения в конец песни для каждого стиля, мы получим количество плейлистов длины ровно X. Если мы как-то умудримся посчитать сумму таких элементов S(X) для всех степеней матрицы от 1 до X, мы получим количество плейлистов длины от 1 до X. Тогда ответом задачи будет S(maxLength)-S(minLength-1). А считать суммы в непрерывном интервале можно по формуле: S(1)+S(2)+...+S(X) = (S(X/2)+1)*[S(1)+S(2)+...+S(X/2)] (это при чётном X, при нечётном соответственно придётся отдельно прибавить элемент S(X)). Короче говоря, возни много.
Обойтись без суммирования матриц можно, если несколько видоизменить матрицу переходов, а конкретно - добавить в вершину, соответствующую концу плейлиста, из которой будут переходы только в саму себя. Тогда количество плейлистов длины от 1 до X будет храниться в элементе матрицы, соответствующем этой самой вершине.

В итоге SRM выдался довольно тяжелым, со всеми задачами в первом дивизионе справилось лишь 3 человека. Хотя в наших краях была глубокая ночь, и многие могут сослаться на это, оправдывая свои неудачи. Так или иначе, я снова получил удовольствие и до Нового года попытаюсь опять собраться с мыслями и выдать ещё один проблемсет ;)

SRM 440

После возвращения с зимней школы, у меня была пара свободных недель до начала следующего семестра в университете, и я уделил время созданию задач для своего второго матча на топкодере. На этот раз я написал 6 разных задач, но концепт обеих Easy и обеих Medium был общий, и в случае Medium-ов мне это очень нравилось.

Ответа я ждал примерно месяц. За это время сменился координатор задач на топкодере - Олексия сменил Иван Метельский. Ответил мне уже последний. Посмотрев задачи, он довольно скоро предложил мне выбрать матч - и я взял первый же неночной SRM после финала ACM.

Тестера на матч назначили в тот день, когда мы с финала вернулись, и им, к моей большой радости, оказался не кто иной, как Вася. За дело он принялся довольно скоро, а расправился с задачами ещё быстрее. Более того, он написал быстрое и красивое решение для div1 Hard, на которое я в итоге и заменил своё страшное и неповоротливое детище.

Опишу вкратце подходы к задачам:
Div2 Easy - IncredibleMachineEasy. Действительно, есть такая старая игра от компании Sierra, и когда-то я в неё играл. Было весело. Так вот, написав уравнение зависимости времени, ускорения и высот падений шариков, мы получим что-то этакое: T=sqrt(2*h1/a)+sqrt(2*h2/a)+...+sqrt(2*hN/a). Умножив обе части уравнения на sqrt(a)/T и возведя получившееся в квадрат, мы придём к формуле для ускорения: a=2*(sqrt(h1)+sqrt(h2)+...+sqrt(hN))/T]^2. Альтернативой этому подходу был перебор ускорения двоичным поиском: проверить, годно ли то или иное значение, можно подставив его в первоначальную формулу.

Div1 Easy - IncredibleMachine. Тут мы видим уже усложнённый вариант: в дело вступают наклонные плоскости. Решать задачу можно опять чисто аналитически, но в данном случае, на мой взгляд, намного легче применить двоичный поиск. Несмотря на то, что в условии даны были все формулы, кто-то всё равно посчитал его не достаточно ясным. Мне трудно судить, хотя учитывая, что большинство всё же решило задачу довольно быстро, наверное, условие всё же было понятным. Так или иначе, приносить задачи физического характера на топкодер довольно тяжело, потому что сложно описать все допущения и условия, принятые в задаче относительно классических законов физики.

Div2 Medium - MazeWanderingEasy. Задача эта возникла как дополнение к её более сложному собрату из первого дивизиона. Я на самом деле видел по Discovery программу, где подобным экспериментом показывали, как изменялись умственные способности мышей при прослушивании различной музыки. Несмотря на то, что я слушаю большей частью металл, подобная задача показалась мне весёлой (хотя кто-то воспринял условие MazeWandering как личное оскорбление :D). Что касается решения, надо было всего лишь найти путь в дереве между двумя вершинами и посчитать на нём количество вершин с decision-ами, то есть именно то, что сказано в условии.

Div1 Medium - MazeWandering. Я люблю задачи на вероятность, поэтому появление такой задачи на моём матче было лишь вопросом времени. Как только вспомню, как я её решал - сразу напишу ;)

Div2 Hard - WickedTeacher. Человеку, знакомому с динамическим программированием и решавшему задачи на битмаски, задача не должна показаться особо оригинальной. Понятно, что вероятность равна отношению [количества таких перестановок входящих фрагментов, для которых итоговое число делится на K] к [общему количеству перестановок, то есть собственно N!]. А для того, чтобы считать число в знаменателе, надо уметь считать NUM(mask,rem), то есть количество перестановок входных фрагментов, составленных из множества, определённого mask, и дающих при делении на K остаток rem. Всего аргументов у NUM может быть 2^N * K штук, что составляет примерно 3*10^6. В конечном счёте, в задаче было над чем повозиться, и решил её один-единственный участник.

Div1 Hard - SquareFreeSets. К этой задаче я видел два различных подхода. Первый, который я заметил в пяти из 7 прошедших systest решений и который описан в editorialе - перебор с запоминанием. Второй, который и использовал Вася - динамическое программирование. Положение описывается тремя параметрами: какие числа уже рассмотрены (а так как их можно рассматривать по возрастанию, то надо запоминать только наибольшее), сколько чисел взято в наше множество и маска простых чисел, которые уже использованы при составлении множества. Ясно, что маску всех простых запоминать невозможно - а достаточно запомнить маску тех простых, которые в квадрате не превосходят N. Чтобы не повторять варианты при рассмотрении чисел, делящихся на более большие простые, надо при рассмотрении простого числа, большего sqrt(N), сразу рассмотреть все кратные ему числа, и вообще исключить их из рассмотрения позднее.

Обзор матча можете посмотреть здесь. Сам я был очень доволен результатами, и матч был, на мой взгляд, очень интересный.

ACM ICPC World Finals 2009 - Stockholm

This Olympiad-related post is a stub. Unfortunately, you cannot alter its content by simply clicking the Edit button. However, you are welcome to leave the appropriate stories in the comments.

SRM 433

Как известно, на топкодере довольно часто проводятся алгоритмические соревнования высокого уровня, называемые SRM-ами (Single Round Match). Каждый SRM, или попросту матч, длится примерно два часа. Первые 75 минут (называемые Coding Phase) участники занимаются непосредственно решением предложенных задач, затем идёт пятиминутный перерыв (Intermission), затем в течение пятнадцати минут (Challenge Phase) у соревнующихся есть возможность посмотреть на решения, присланные своими противниками, и попытаться их "зачеленджить", т.е. придумать такие данные, для которых решение не будет работать правильно. Потом некоторое время люди ждут окончательных результатов, болтают о том - о сём, сетуют на всё повышающееся количество китайских участников, и расходятся.

Учитывая, что уровень участников очень неоднородный, каждый матч проводится в двух дивизионах. Люди, имеющие более высокий рейтинг, соревнуются в первом, более низкий - соответственно, во втором дивизионе. Главное отличие между дивизионами - это предложенные задачи. В обоих дивизионах их по три. В рамках одного дивизиона задачи делятся на лёгкую, среднюю и сложную. Тем не менее, задачи первого дивизиона на порядок сложнее задач второго (лёгкая задача в первом дивизионе часто используется как средняя для второго). Так или иначе, для проведения матча всегда нужно от 4 до 6 более-менее оригинальных задач разного уровня сложности.

Упомянутое в первом абзаце "довольно часто" в конце 2008 года равнялось примерно четырём матчам в месяц. Человеку, хорошо знакомому со спецификой олимпиадных задач, должно быть понятно, что один и тот же человек или группа людей не в состоянии каждую неделю выдавать оригинальный комплект интересных задач. Так вот топкодер этого и не делает - он даёт возможность самим участникам предлагать свои задачи в обмен на некоторое денежное вознаграждение. То есть любой пользователь,
достигший 18 лет, имеющий определённый рейтинг и количество проведённых матчей, может придумать свои задачи и, если они достаточно интересные, он получает шанс стать автором матча.

Провести свой собственный матч уже давно было моим заветным желанием, и ещё осенью у меня были готовы задачи, так что я терпеливо ждал своего шанса. И он появился примерно в то же время, когда мне предложили поработать на сборах. То есть в то время за мной закрепили SRM 433, дата которого была 21 января.

Процесс получения SRMа выглядит примерно так. Сначала человек делает наброски своих задач в специальном приложении MPSQAS, иначе говоря пишет условия, и необязательно оконченные. Потом надо написать администратору, ответственному за выбор задач, с просьбой посмотреть на плоды своих мучений. Рано или поздно ему приходится взглянуть на задачи, и тогда по каждой он или задаёт дополнительные вопросы, потому что наброски часто слишком далеки от совершенства, или сразу отклоняет, чаще всего потому, что она слишком неоригинальная и уже была на топкодере пару десятков раз, или утверждает её. Имея утвержденные задачи всех уровней для обоих дивизионов (в принципе, пару лёгких могут и простить для начала), можно смело просить SRM. Я не уверен, чем админы руководствуются, отдавая тот или иной матч в чьи-то руки, но могу сказать, что лично меня до сих пор не обижали.

Получив SRM, надо доводить его до ума. То есть если не хватало какой-либо задачи, надо её придумать, все условия надо максимально отточить, надо написать авторские решения - причём обязательно на Java, и на всех возможных тестах решение не должно работать больше 1 секунды, и
надо добросовестно составить эти самые тесты. Потом за дело берутся люди, на которых возлежит ответственность за то, чтобы всё было максимально точно, правильно и понятно. По моему опыту, таких бывает трое: администратор, ответственный за выбор задач, тестер и PabloGilberto, который занимается исключительно английским языком. Выбор тестера происходит сразу после утверждения матча.

На моём первом SRMе координатором по задачам был OlexiyO, а тестером выступал Иван Метельский. Особо много нам мучаться не пришлось (разве лишь что меня заставили рисовать дополнительные картинки в div1 Medium), и день матча подошел довольно быстро. Перед матчем автору дают специально сгенерированный пароль от ника writer, который обладает разными прикольными функциями. Этот ник в арене обладает администраторскими привилегиями, и позволяет читать все чаты в арене, в том числе шепот. Хотя часто это становится просто проклятием, потому что чата чрезвычайно много. Также во время Coding Phase можно видеть коды любых участников. Вообщем, во время матча не соскучишься.

Что касается моих задач, бегло пройдусь по основным идеям:

Div2 Easy - RoyalTreasurer. Довольно стандартная задача - очевидно, что минимальная сумма достигается, когда наибольшие элементы первого массива сгруппированы с наименьшими элементами второго.

Div2 Medium / Div1 Easy - MagicWords. Несмотря на низкие ограничения, просто перебрать все возможные перестановки слов и проверить каждую тривиальным алгоритмом не получалось, или по крайней мере не должно было получаться. Есть множество методов, с помощью которых можно ускорить эту проверку: хеширование, KMP, технические оптимизации. Авторский вариант основывался на следующем наблюдении: если строка длины L повторяется в своих shift-ах ровно K раз, то она является периодической с периодом, равным L/K - и наоборот. Таким образом, надо было проверять периодичность строки для периодов, равных делителям L.
Ещё одно решение, которое я сначала не заметил, но потом мне очень понравилось, основывалось на том, что сместив последнее слово в нашей перестановке в начало, мы получаем строку с таким же множестов shift-ов. Таким образом, можно было перебирать все перестановки первых (N-1) строк, а последнюю всегда ставить в конец - тогда итоговый ответ получается при умножении полученного количества магических строк на N.

Div2 Hard - MakingPotions. Идеей решение похоже на алгоритм Дейкстры - на каждом шагу помечать полученным то снадобье, которое ещё не получено и имеет наименьшую цену. Если таким образом мы дойдём до LOVE, то получим его за наименьшую возможную цену, если нет - оно не достаётся. Проблемы могли возникнуть при парсировке входных данных, или с теми ситуациями, когда цены становились слишком большими.

Div1 Medium - SettingTents
. Задача, которую решили, к моему удивлению, меньше ста человек, что для Medium в принципе маловато. На самом деле в ней проходил даже алгоритм сложности O(N^5), т.е. перебрать обе координаты обеих вершин диагонали ромба, а затем пройти одним циклом по длине второй диагонали и проверить, попадают ли её концы в целочисленные точки. От этого цикла можно было избавиться несложными математическими вычислениями. Во время матча большей частью были имплементированы более быстрые алгоритмы. Недавно я натолкнулся на довольно старый пост в блоге Petr-а, в котором были рассмотрены методы решения подобной задачи - советую посмотреть.

Div1 Hard - BarbarianInvasion. "Праздник потока", как её потом обозвали. Действительно, задача требовала нахождение минимального вершинного разреза, только при условии, что в первую очередь должно быть минимизировано количество вырезанных вершин, а потом их суммарная стоимость. В таком случае применяют следующий фокус: весом вершины делаем её стоимость + некую большую константу X, которая заведомо больше любой возможной суммарной стоимости вырезанных вершин при данных в задаче ограничениях. Тогда, найдя величину минимального разреза ANS между столицей и граничными клетками, мы будем иметь минимальное количество вырезанных вершин как ANS/X и минимальную стоимость этих вершин (при условии минимизации их количества) как ANS%X.

Можете также посмотреть editorial этого матча и его результаты.

Wednesday, July 8, 2009

Сборы кандидатов в Бакуриани

После полуфинала я решил расслабиться и позволял себе выступать только на топкодере. В принципе, смотря сейчас на мои тогдашние результаты, лучше б и не позволял :)

Не помню, до каких пор я планировал отдыхать, но в последних числах декабря я получил звонок от Deputy Leader'а грузинской сборной школьников по информатике, Гочи Мандария. В начале января планировалось проведение зимних сборов для кандидатов в сборную, и мне предложили позаниматься с детьми несколько дней. Это был первый раз, когда ко мне обратились с предложением подобного рода, а поработать с ребятами мне давно хотелось, поэтому я согласился без лишних раздумий, несмотря на довольно ограниченное время, остававшееся до начала сборов. Таким образом, предновогодние дни я провёл, с большим воодушевлением готовя материал для лекций и соответствующие ему задачи.

Сборы проводились в Бакуриани, на базе тамошней школы №1 (не хочу соврать, но вроде она там и единственная). Компьютерный класс там такой, какому позавидует по крайней мере большинство тбилисских школ, плюс к тому школа оснащена солнечными аккумуляторами и электричество работает без сбоев. А снаружи в это время стояла очаровательная зимняя погода.


В моём распоряжении было 5 дней, один из которых попадал на Рождество, и поэтому заниматься в него никто и не думал. Зато остальные четыре дня я собирался мучать детей по полной. Первые три дня я собирался проводить лекцию, а затем 3часовый контест по школьным правилам, состоявший из 3 задач на тематику объясненного материала. На последний день у меня был припрятан 5часовый контест из 5 задач на все темы вперемешку.

В итоге всё шло примерно по плану. У нас царила здоровая, весёлая атмосфера, которая не мешала ребятам концентрироваться на контестах.


Темы первых дней у меня были следующие: бинарный и тернарный поиск в первый день, битмаски во второй, а на третий ко мне присоединился Леква, и общими усилиями были разобраны деревья отрезков и поиск в ширину на графе с ребрами длины 0 и 1. Задачи, которые я составил для тех сборов, потом появились на различных контестах, к созданию которых я приложил руку - в том числе на туре, проведённом нашей командой на сборах в Харькове, и моём мини-контесте на armcoderе.

А между вторым и третьим днём был вышеупомянутый выходной, и мы вдоволь накатались на лыжах.


Также имела место эпохальная битва в джокер, в которой Ника Габисония и Гоча Мандария были повержены, за что одному пришлось лепить снеговика, а второму его украшать.


Ну а в мой последний день и мне, и Лекве пора была уматывать домой, а нас должны были сменить другие специалисты. Поэтому мы оставили ребятам задачи на 5 часов и сели в маршрутку. С утра погода не предвещала ничего зловещего, но по дороге к Тбилиси собрались тучи, поднялся страшный ветер, пошёл град, и мы были благодарны судьбе, когда наконец доехали. Как потом оказалось, в Бакуриани вообще была буря, так что не поспеши мы тогда, могли застрять надолго. Зато мы пропустили невероятное сражение в снежки, которое разразилось на следующий день в рядах нашей делегации и в результате которой кое-кого накормили большой кучей снега. Что поделать, каждому своё...

[aq unda iyos TovliT naWami varamas suraTi. visac mogepovebaT, dadeT :D]