Блог пользователя CleRIC

Автор CleRIC, 10 лет назад, По-русски

385A - Медведь и малина

В этой задаче нужно было понять, что ответ это максимум из a[i] - a[i - 1] - c, для i = 2..n и не забыть, что ответ не может быть отрицательным, так как медведь может не занимать в долг бочонок меда.

385B - Медведь и строки

В этой задаче нужно было написать решение оптимальней наивного. Для этого, например, можно перебирать первым циклом левый индекс l рассматриваемой подстроки, а вторым циклом правый индекс r рассматриваемой подстроки (l ≤ r). Если на какой-то позиции i нашлась подстрока "bear", значит все подстроки x(l, j) (i ≤ j), также содержат "bear" в качестве подстроки. Значит к ответу можно сразу прибавить |s| - j + 1 и выйти из второго цикла. Также требовалось понять, что если в строке x(l, j) не было подстроки "bear", тогда в строке x(l, j + 1) подстрока "bear" могла появиться только в последних четырех символах.

385C - Медведь и простые числа

В этой задаче нужно было решить несколько подзадач:

1) Посчитать количество вхождений каждого числа от 2 до 107 в данный в задаче набор чисел. Это можно делать быстро так. Завести массив count на 107 элементов и при считывании чисел прибавлять count[x]++.

2) Теперь научимся считать f(x).

Для начала нужно найти все простые числа до 107 и посчитать для каждого простого числа — f(x).

Как посчитать f(2)? Нужно сложить count[2],count[4],count[6],count[8],...

Как посчитать f(5)? Нужно сложить count[5],count[10],count[15],count[20],...

Как посчитать f(x)? Нужно сложить count[x],count[2·x],count[3·x],count[4·x],...

Можно заметить похожесть на алгоритм решета Эратосфена http://e-maxx.ru/algo/eratosthenes_sieve и немного видоизменить его. Также будем сохранять в массиве pre результаты этих вычислений. А именно pre[x] = f(x).

3) Теперь можно посчитать префиксные суммы на массиве pre. Это делается одним проходом слева направо, прибавляя pre[i - 1] к pre[i].

4) Зная префиксные суммы, можно отвечать за O(1) на запрос [l, r]. Это делается так pre[r] - pre[l - 1].

5) Теперь можно считывать запросы и сразу отвечать на них. При этом не стоит забывать, что правая граница в запросе может быть до 2·109, поэтому правую границу можно всегда уменьшать до 107, так как бОльших чисел в изначальном массиве все равно нет.

385D - Медведь и прожекторы

В этой задаче нужно было понять, что если дорога уже освещена расстоянием в dist, то следующим прожектором оптимально освещать так, чтобы левая точка освещения на оси X была равна l + dist.

Предположим, что сейчас дорога освещена с l до d. Как теперь найти самую правую точку на оси X, которая будет освещена следующим прожектором?

Для этого достаточно использовать понятие вектора и матрицы поворота.

Находим вектор (dx, dy) от прожектора до точки (d, 0). (dx, dy) = (d - x, 0 - y).

Далее этот вектор нужно повернуть на angle градусов. Для этого можно использовать матрицу поворота.

(dx, dy) = (dx·cos(angle) - dy·sin(angle), dx·sin(angle) + dy·cos(angle))

Далее этот вектор нужно домножить на k таким образом, чтобы dy стал равен единице.

Ну и теперь можно определить самую правую освещенную точку на оси X. Она равна x - y·dx.

Также не стоит забывать, что правая точка может находится где-то в бесконечности.

На этом геометрия в этой задаче закончилась.

Теперь нужно научиться быстро находить оптимальный порядок прожекторов.

Для этого стоит применить подход динамического программирования. А именно, хранить ответ для масок прожекторов.

dp[i] = оптимальный ответ для такой-то маски i. Обычно под масками подразумевают целое число, в строковой бинарной записи числа которого, стоят 0 и 1. Допустим на 2 позиции стоит 1 — это означает, что 2 прожектор уже был использован. Например, dp[6] — (61102) оптимальный ответ, если уже использованы 2 и 3 прожектора.

Идея теперь такая. Перебираем маски в динамике dp[i]. Перебираем в i маске неиспользованные прожекторы j и обновляем ответ для маски, где этот прожектор уже используется — dp[ i or 2j ] = max( dp[ i or 2j ], dp[ i ] + вычисление_самой_правой_точки()). Так как мы уже знаем как находить самую правую освещенную точку, то обновление ответа для новой маски не составит труда.

385E - Медведь в поле

В этой задаче можно было заметить несколько вещей:

1) Заметить, что решение моделированием не проходит по времени, так как t  ≤  1018.

2) Далее можно убедиться, что задачу не решить отдельно по x и отдельно по y, так как x и y зависят друг от друга при вычислениях.

3) Также не проходит достаточно стандартный метод с поиском цикла (то есть мы попадаем в тоже самое состояние через некоторый небольшой промежуток времени). Такого может не произойти долгое время, так как ограничения на координаты большие.

Как тогда решать.

Пусть у нас есть матрица (xi, yi, dxi, dyi, ti, 1).

Умножив ее на такую матрицу long long base[6][6] = {

{2,1,1,1,0,0},

{1,2,1,1,0,0},

{1,0,1,0,0,0},

{0,1,0,1,0,0},

{0,0,1,1,1,0},

{0,0,2,2,1,1} };

мы получим значения на следующем шаге.

Откуда взялась эта матрица? Давайте распишем как меняются параметры с каждым шагом и увидим похожесть на матрицу.

x = x + y + dx + dy + t + 0·1.

y = x + y + dx + dy + t + 0·1.

dx = x + y + dx + dy + t + 2·1.

dy = x + y + dx + dy + t + 2·1.

t = x + y + dx + dy + t + 1·1.

1 = x + y + dx + dy + t + 1·1.

Таким образом, возведя матрицу base в степень t - 1, и потом умножив матрицу (sx, sy, dx, dy, t, 1) на base, получим значения в момент времени t.

Матрицу можно возводить в степень быстро по принципу быстрого возведения в степень по модулю. http://e-maxx.ru/algo/binary_pow

Перемножаются матрицы за куб. Итоговое количество операций 63·log(t)

Разбор задач Codeforces Round 226 (Div. 2)
  • Проголосовать: нравится
  • +85
  • Проголосовать: не нравится

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится

Great Editorial!

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

There's no english editorial? :/

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Все-таки матрица из одного столбца в математике называется вектором :)

»
10 лет назад, # |
Rev. 7   Проголосовать: нравится +28 Проголосовать: не нравится

I solved E (theoretically, I don't really want to implement it) by solving the system of equations:

x(t) = [x(t - 1) + vx(t) - 1]%N + 1
y(t) = [y(t - 1) + vy(t) - 1]%N + 1
vx(t) = vx(t - 1) + t - 1 + x(t - 1) + y(t - 1)
vy(t) = vy(t - 1) + t - 1 + x(t - 1) + y(t - 1)

for $t > 0$, where the values of (x, y, vx, vy)(0) are given as input parameters, and the time is 0-based.

Firstly, we want to get rid of the modulo function. We can't just compute all variables modulo N, because there's the -1, so we'll shift the coordinates to (x', y')(t), where x' = x - 1, y' = y - 1. Now the equations become

x'(t) = x'(t - 1) + vx(t)
y'(t) = y'(t - 1) + vy(t)
vx(t) = vx(t - 1) + t + 1 + x'(t - 1) + y'(t - 1)
vy(t) = vy(t - 1) + t + 1 + x'(t - 1) + y'(t - 1)

where all variables are computed modulo $N$ (we'll omit that from now on). We can compute (x, y, vx, vy)(1) from this, and further substitute for vx, vy, which gives for t > 1

x'(t) - x'(t - 1) = x'(t - 1) - x'(t - 2) + t + 1 + x'(t - 1) + y'(t - 1)
y'(t) - y'(t - 1) = y'(t - 1) - y'(t - 2) + t + 1 + x'(t - 1) + y'(t - 1)

Let's now define

s(t) = x'(t) + y'(t)
d(t) = x'(t) - y'(t)

using which we can rewrite the sum and difference of the equations above to

d(t) - d(t - 1) = d(t - 1) - d(t - 2)
s(t) - s(t - 1) = s(t - 1) - s(t - 2) + 2(t + 1) + 2s(t - 1)

Once again, we define $q(t)=s(t)+t+2$ (actually, it's s(t) + t + c, and we compute the constant c by substituting and trying to get the constant term to 0), and rewrite our equations to

d(t) = 2d(t - 1) - d(t - 2)
q(t) = 4q(t - 1) - q(t - 2)

which can be solved explicitly (I'm lazy, so I'm just using Wolfram Alpha, read more about linear recurrent equations on Wikipedia or something):

d(t) = C * t + D

where the parameters $A..D$ are given by the values for t ≤ 1.

This is more of a theoretical solution (since as long as we get the recurrences for d(t) and q(t), it's best to use matrix multiplication), but I just wanted to do it this way :D

»
10 лет назад, # |
Rev. 23   Проголосовать: нравится 0 Проголосовать: не нравится

i think the matrix should be that: {2,1,1,1,0,0},

{1,2,1,1,0,0},

{1,0,1,0,0,0},

{0,1,0,1,0,0},

{0,0,1,1,1,0},

{0,0,0,0,1,1} };

i tried and solved it. with this matrix.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Rev. 23????! How could this happen?! :D

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится

      Maybe for the same reason as rev.7 of my comment above — I edit my comment, click "Save", nothing happens; I wait until my internet connection is stronger, click again, and nothing happens again, etc., until I lose patience and reload the page. And look what happened: the revisions were counted, but my comment wasn't edited. Some bug of CF, maybe.

»
10 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится
По-моему, явно лучший раунд за последние несколько месяцев. Разнообразные и очень красивые задачи на разные жанры. Может,  большой разрыв по сложности между C и D, но в целом очень понравилось.
»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

В задаче С я написал такое же решение, как тут (на GNU C++), и получил TL. Что у меня не так?

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Nice editorial. Anyways, I had a sense that explanation of problem E does not give you an idea of how you can come up with that solution. Let me clarify that: The state can be described by following variables: x — where is the bear currently (x-coordinate); y — where is the bear currently (y-coordinate); dx — the current speed towards X axis; dy — the current speed towards Y axis; t — time passed after the start;

This information is enough to describe a state. Now let's see how the state changes: (dx)' = dx + (x+y+t), (dy)' = dy+(x+y+t), (x)' = x + (dx)' = 2x+y+dx+t, (y)'=x+2y+dy+t, (t)'= t+1.

As we see, the new state is similar to linear combination of previous state components, except for t=t+1 (1 is not in a state). It is very similar to matrix multiplication, except for we don't have 1. So we can make a matrix this way: Let's say the state is (1x6) matrix : (x, y, dx, dy, t, 1) and the matrix (M) is 100001 021110 012110 010100 001010 011111 It's easy to see why the new state is the old state matrix multiplied by M. The rest is easy, our final state is going to be the initial state matrix multiplied by the T-th power of M. Of course we're gonna use the fast exponentiation. (The naive multiplication is fine here, because the sizes are too small)

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

About Problem D ,!

how u calculate calc_rightmost_lighted_point() without keeping track of the last right_most_point u get till this state !

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Problem D !?!

how u can calculate calc_rightmost_lighted_point() in ur Dp without keeping the last right_most_point u can get till before this state

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

By the way, in problem D you can use law of sines to find the distance that is lighted with some floodlight.

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

In problem C , i can't understand why we add pre[i-1] to pre[i]?

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    If you iterate i from 2 to n-1 adding pre[i-1] to pre[i], every new pre[i] will contain sum of all pre from 1 to i

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Thank you! one more question how to prove that pre[r]-pre[l-1] is answer of query?

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        I think it is clearer if we denote Cnt[i] = f(i) and Sum[i] = Cnt[1] + Cnt[2] + ... + Cnt[i]. Now, the answer for a query on [l, r] is Sum[r]-Sum[l-1].

        Sum[r]-Sum[l-1] = (Cnt[1] + Cnt[2] + ... + Cnt[r])-(Cnt[1] + Cnt[2] + ... + Cnt[l-1]) = [(Cnt[1] + ... + Cnt[l-1]) + (Cnt[l] + Cnt[l + 1] + ... + Cnt[r])] — (Cnt[1] + ... + Cnt[l-1]) = Cnt[l] + Cnt[l + 1] + ... + Cnt[r].

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    -emli- ReekinAcer can u help me please. here my code for C and get WA at tc 4 !! 9731769

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

А какая сложность решения получается в задаче D?

  • »
    »
    10 лет назад, # ^ |
    Rev. 4   Проголосовать: нравится -6 Проголосовать: не нравится

    O(2nn)
    UPD2: да, я не прав был. Можно было бы и написать.

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Nice editorial! But I suppose that a link to a solution implementing the idea outlined in the editorial for every question would help us understand them even better!

  • »
    »
    10 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Well, you can use "Status filter"

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Well, not all the accepted solutions use the idea mentioned in the editorials. It's a bit inconvenient browsing through all accepted solutions to find the one which does.

»
8 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

По-моему, в задаче A(Div. 2) надо найти максимум из a[i] - a[i + 1] - c для i = 1...n — 1. А написано что a[i] - a[i - 1] - c для i = 2...n

»
7 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

In problem C, I did made a cnt array (or say a hashmap) and did find all primes below the maximum x using Sieve of Erathosthenes, then for each prime I iterated over every number and and found f(p) and stored them in a Binary Index Tree, but that didn't help. I believe my complexity is O(n(logn)(loglogn)+m(logn+logP)+PlogP) where P(664,579~10^7) is the count of primes below maximum x so total operations are around 5e6+6e7+4e7 but it has a TLE?.This is my submission.

»
4 года назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

can anyone help me out? I have tried 385C and it gives me a runtime error on test case 4 link to my code — https://ideone.com/fork/GMagWh

  • »
    »
    4 года назад, # ^ |
    Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

    I don't know if you are still looking for this :

    That might be because x or y i.e the query ranges might be going out of limits. Also it may help the others who attempt it.

    Edit : Also if anyone is getting TLE even after implementing same approach use:

    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    
  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Reduce any l or r to 10^7 if it is greater than 10^7. Try this case 1 2000 1 1424767024 1629755604