Вчера завершился третий отборочный интернет-тур в ЗКШ. Было бы интересно, я думаю, обсудить задачи. В частности, очень интересно, как решать вторую задачу.
№ | Пользователь | Рейтинг |
---|---|---|
1 | tourist | 3985 |
2 | jiangly | 3814 |
3 | jqdai0815 | 3682 |
4 | Benq | 3529 |
5 | orzdevinwang | 3526 |
6 | ksun48 | 3517 |
7 | Radewoosh | 3410 |
8 | hos.lyric | 3399 |
9 | ecnerwala | 3392 |
9 | Um_nik | 3392 |
Страны | Города | Организации | Всё → |
№ | Пользователь | Вклад |
---|---|---|
1 | cry | 169 |
2 | maomao90 | 162 |
2 | Um_nik | 162 |
4 | atcoder_official | 161 |
5 | djm03178 | 158 |
6 | -is-this-fft- | 157 |
7 | adamant | 155 |
8 | awoo | 154 |
8 | Dominater069 | 154 |
10 | luogu_official | 150 |
Вчера завершился третий отборочный интернет-тур в ЗКШ. Было бы интересно, я думаю, обсудить задачи. В частности, очень интересно, как решать вторую задачу.
Название |
---|
Во-второй можно, например, сначала разложить число в d-ичной системе счисления и записать в виде: d^k + d^k + d^k + d^(k — 1) + d^(k — 2)... А затем рекурсивно начать выносить за скобки максимально возможные степени d на всех префиксах разложения от конца до 1 (чтобы все степени вхождения d в скобке были >= 1).
Для d = 1 можно просто разложить число для d = 2, а затем представить все двойки как (1 + 1).
a[1] * d + d * (a[2] * d + d * (a[3] * d + d * (... Это разложение числа N в систему счисления по основанию d. a[i] — сколько d^i входит в число. Если a[i] == 0, то пропускаем это слагаемое. Иначе a[i] * d = d + d + ... + d — a[i] раз. Про d == 1 написали выше.
Как решать третью задачу?
Отсортируем оба массива (a[], b[], ноль-индексация) по возрастанию. Заметим, что мы при оптимальном распределении a[n — i + 1] сопоставляется b[i] количество баллов. Посчитаем максимум на префиксах данного нового массива, назовем его pr[]. Теперь, если a[i] + b[n — 1] > pr[n — i — 2](нер. 1), то участник, имеющий кол-во баллов a[i], может стать победителем. Действительно, все участники, имеющие изначально меньшее число баллов, чем i-ый получат меньшую прибавку b[j], чем i-ый участник, а все участники, имевшие изначально большее число баллов, чем i-ый также будут иметь меньше баллов, чем i-ый участник (по нер. 1).
Асимптотика: NlogN
Код: http://pastebin.com/V8DbGKcg
Может кто-нибудь скинуть рабочий код к F?
Задача E:
У каждого палиндрома есть либо центр длины 1, если он нечетной длины, либо центр длины 2, если он четной длины. Таким образом строка является палиндромной только если найдется такое i, что s[i] = s[i+1] или s[i] = s[i+2].
Обозначим за F(x) количество антипалиндромных чисел, строго меньших x.
Тогда ответ на задачу F(R) — F(L) + good(R) (good(R) — 1 или 0 в зависимости от того, является число R антипалиндромным или нет).
Единственная сложность в том, чтобы посчитать F(x).
Если длина числа x равна 1, то все ясно.
Мы можем перебрать длину префикса, который будет общим для какого-то подходящего антипалиндромного числа и нашего числа x.
Пусть длина общего префикса 0. Тогда на первую позицию станет любая ненулевая цифра, меньшая, чем первая цифра в x. Количество таких цифр можно посчитать за О(1) и обозначить за C. На вторую позицию станет любая цифра, отличная от первой. На позиции 3 и дальше можно будет поставить любую цифру кроме последней и предпоследней поставленных. Итого получаем формулу: C * 35 * (34 ^ (len — 2)).
Теперь для ненулевой длины общего префикса.
Пусть мы зафиксировали эту длину — pref.
На позицию pref+1 подойдет любая цифра, которая меньше x[pref+1] и не равна 0, x[pref] и (x[pref-1] если pref>1). Количество таких цифр опять же можно посчитать за О(1) и обозначить за С.
Ну и по аналогии со случаем pref = 0, для каждой цифры правее будет ровно 34 варианта.
Суммируем количества по всем pref от 0 до len(x)-1, получаем какую-то часть F(x).
Мы забыли учесть числа, которые длиной меньше x.
Просто прибавим к значению F(x) значение dp[len(x) — 1], где dp[i] обозначает количество антипалиндромных чисел длиной до i включительно и считается следующим образом:
dp[i] = 36, i = 1
dp[i] = dp[1] + 35 * 36, i = 2
dp[i] = dp[i — 1] + 34 * dp[i-1], i > 2
С F(x) все. Как написать good(x), думаю, понятно)
Как решать задачу D?
два квадратичных дп
f1[i][j] — это какое минимальное количество раз надо перейти с одной строки на другую(мин количество разрезов) при этом последней будет первая строка (ответ для первых i элементов первой строки и для j первых элементов второй)
f2[i][j] — это какое минимальное количество раз надо перейти с одной строки на другую(мин количество разрезов) при этом последней будет вторая строка (ответ для первых i элементов первой строки и для j первых элементов второй)
Очевидно что f1[0][0] = 0 и f2[0][0] = 0 во всех остальных INF
пускаем форы i от 0 до s1.length() , j от 0 до s2.length(). Теперь мы стоим в i,j Очевидно что текущий символ из строки s имеет индекс (i + j) — 1 (если нулевая индексация)
Теперь если (s[i + j — 1] == s1[i — 1] && i > 0) то мы можем засунуть этот символ в первую строку и значит считаем f1[i][j]
Аналогично с f2
Ответ равен min(f1[s1.length()][s2.length()] , f2[s1.length()][s2.length()])
Вот рабочий код http://pastebin.com/aDA1r0EJ