Я расскажу как я решал задачи, которые я сдал.
Мне, в свою очередь, интересно, как решать B :о)
Очень клевый контест для командной работы -- в задачах надо много думать и не очень много кодить. Но все равно поверить, что кто-то на ней сдал девять задач невероятно :о
Результаты с тимуса: http://acm.timus.ru/monitor.aspx?id=83
Результаты с петрозаводска: http://karelia.snarknews.info/index.cgi?data=macros/run&menu=index&head=index&round=01&sbname=2010s&class=2010s
Задача C.
Можно заметить, что окружность вписывается тогда и только тогда, когда произведение радиусов окружностей, между которыми мы ее вставляем, является квадратом рационального числа. Более того, если их радиусы равны A/(B^2) и A/(C^2), то радиус впихнутой окружности будет A/((B+C)^2). То есть если с самого начала можно впихнуть окружность, то можно будет и на каждой следующей итерации, и наоборот. Отсюда, сначала проверим, является ли произведение данных нам радиусов квадратом рационального числа, и, если да, представим радиусы в виде
r1 = (a) / (b)
r2 = (a) / (c)
Где a = r1*r2/gcd(r1,r2). После этого будем на каждой итерации вычислять радиус центрального шарика, и смотреть, с какой стороны относительно центрального шарика нужный нам - и продолжать рекурсивно.
Отдельно надо рассмотреть крайний случай, когда впихнуть шарик нельзя, но запрашивается один из крайних.
Задача G.
Решим по очереди для каждого делителя N, и в конце для N, так, чтобы к моменту, когда мы решаем для некоторого делителя, для всех меньших делителей мы уже знали ответ.
Теперь, чтобы решить для N перебираем все делители N, для каждого делителя смотрим, каков шанс нарваться на этот делитель в интервале [1,10^18], причем так, чтобы при этом не делилось ни на какой больший делитель. Это делается с помощью включения-исключения. Допустим, что мы решаем для числа 12, и хотим узнать, каков шанс нарваться на число, кратное двум, но не кратное четырем или шести. Ответ будет
chance = ( 10^18 / 2 - 10^18 / 4 - 10^18 / 6 + 10^18 / 12 ) / 10^18
Для каждого делителя A прибавляем к ответу ( ans[A] + ans[N / A] ) * chance.
В конце в ответе надо учесть, что, прежде, чем попасть в любой такой делитель, мы сколько-то раз потыкаемся в взаимнопростые числа. Это учитывается как-то так:
ret = ( ret + 1 ) / (allChances);
Где allChances - это сумма всех chance для всех делителей N.
Задача I.
Надо найти N такое, что следующая формула вернет ноль:
- a[n - 1] + (n-1)/n * (- a[n - 2] + (n-1)/n * (- a[n - 3] + (n-1)/n * (...) % n) % n) % n
Восстанавливать надо с конца, получается
ret = 0;
ret += a[n - 1];
ret %= n;
ret *= n
ret /= (n-1)
ret += a[n - 2];
ret %= n^2;
ret *= n;
ret /= (n-1)
...
То есть, тоже самое псевдокодом
for(i from N-1 to 0) {
ret = (ret + a[i]) % mod;
if( i == 0 ) break;
ret *= N;
mod *= N;
ret /= (N-1);
}
Тут самое сложное - это сделать это все быстро. Особенно деление по непростому модулю. Так как это длинная арифметика, и решать надо все равно на Java, кажется очевидным попользовать модный modInverse, но такое решение ловит TLE. Я в конце концов пропихнул такое решение:
for(i from N-1 to 0) {
ret = (ret + a[i] * mul) % (mod_mul);
if( i == 0 ) break;
ret *= N;
mod *= N;
mul *= (N-1);
mod_mul *= N*(N-1)
}
ret = ret * mul.modInverse(mod_mul) % mod;
Задача H вроде тривиальная - ДП по подмножествам.
В задаче D строим для первых 100 элементов, и мучительно угадываем закономерность.
"играешь в квак" имелось ввиду в этот конкретный момент а не вообще :о)
как он не заблокирован, если на мониторе заставка какая-то :о)
Unable to parse markup [type=CF_HTML]
Пусть у нас есть две вершины u и v, тогда мы можем найти стоимость покрытия этими двумя вершинами за O(deg(v)) исполузься сжатую матрицу смежности и списки смежности.
Теперь пусть тогда переберем все пары вершины u и v такие что , и заметим, что таких вершин u не больше . Каждая пара у нас обрабатывается за O(deg(v)), поэтому суммарная стоимость будет . Другие пары проверять (пару у которых степень обоих вершин меньше ) нет смысла т.к. они точно не покроуют все множество вершин. Остался случай когда он решается влоб.
Для решения D использовал следующее: http://ru.wikipedia.org/wiki/Линейный_конгруэнтный_метод
Из текста ссылки следует такое решение:
1) Находим все простые делители числа m, перемножаем их -> prod
2) Если (m - 1) % 4 == 0 -> умножаем полученное произведение на 2 -> prod *= 2
утверждается, что a может быть только 1, prod, prod * 2, ..., a < m
Отсюда уже следует ответ
Круто! Спасибо
О думал как можно без длинки обойтись в задаче С и понял ваш метод. Метод просто супер