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

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

A. Подстрока


Думаю все поймут по коду:



p.s. При больших длинах можно воспользоваться алгоритмом КМП.

B. Третья степень


Ответ равен по модулю P.
Единственная проблема - при вычислении  происходит переполнение.
Как избежать переполнения:
  1. Написать длинку
  2. Написать быстрое умножение по модулю (аналог быстрого возведения в степень)
Объясняю второй способ:



Псевдокод:



Очевидно что работает это за логарифм от b, так как у нас b делится на два каждый раз когда он чётный, а если он не чётный то мы отнимаем от него 1, и он на следующем шагу становится чётным.

C. Функция

Не знал, что проходит наивные решения с предпочётом и закидыванием в сэт или мап.
Ожидались решения с проверкой за О(1) битовыми операциями...
Этот способ должен работать даже если нужно было вычислить f(108)...

И так разбор...
Нужно было сделать то, что написано в условии - пройтись фориком, но быстро проверять.
Как быстро проверять:
Представим себе число X.
Для него существуют такие целые неотрицательные p и q, что 2p - 2q = X если представление X в двоичной записи эквивалентно:
63.........p................q.........0  -  позиции
00000001111111100000  -  число

Заметим, что (2p - 1) - (2q - 1) = 2p - 2q

Теперь рассмотрим 2p - 1:
63.........p...........................0
00000001111111111111.

Рассмотрим 2q - 1:
63...........................q...........0
000000000000000111111

И если отнять 2q - 1 от 2p - 1, то получится то, что нам нужно:
63.........p................q.........0
00000001111111100000


Теперь как проверить число на то, что она в двоичной записи такая 00000001111111100000:
1. Все правые нули сделаем единичками: X|(X - 1). Получится 00000001111111111111
2. Прибавим к 00000001111111111111 единичку. Получится 00000010000000000000
3. И проверяем, что число является степенью двойки(в ней только одна однёрка): X&(X - 1) =  = 0

D. Непростая задачка


Есть несколько способов решить эту задачу. Вот мне известные:
1. Сжатым бором
2. Хэшами (наверняка это самый лёгкий способ)
3. Вроде и суффиксными деревьями тоже решается
4. Говорят прошёл и простой, не сжатый бор...
5. можно с N префикс-функциями, правда памяти N2(добавил Bugman)

Решение хэшами:
1. Нужно перебрать все подстроки.
2. Вычислив их хэши запихнуть в массив.
3. Отсортировать хэши
4. Посчитать количество различных элементов.
Я не буду тут говорить, что такое хэши, а дам лишь ссылку (http://e-maxx.ru/algo/string_hashes) - там всё подробно описано.

E. Подматрица


Так получилось, что и эта задача решается хэшами.

Идея подчёта хэша подматрицы - считать хэш хэшов (способ 1):
h1 =  hash(A1, 1A1, 2 ...  A1, b)
h2 =  hash(A2, 1A2, 2 ...  A2, b)
...
ha =  hash(Aa, 1Aa, 2 ...  Aa, b)
hash(A) =  hash(h1 h2... ha)

Асимптотика O(a * b + c * d).

Идея подчёта хэша подматрицы (способ 2):

В задаче E можно обойтись обычным хэшиком по одному прайму. Если мысленно склеить все строки подматрицы в одну строку, то найти хеш такой строки не составит проблем. Если предпосчитать хеши с каждой позиции на b элементов влево (где это допустимо) и предпосчитать все степени прайма до C * D, то дальнейшее решение можно реализовать за O(C * D) и использовать лишь один прайм.
  • Проголосовать: нравится
  • +5
  • Проголосовать: не нравится

13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
В D прошел несжатый бор.
13 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится
Автору: Слова "однёрка" не существует. Используй "единица".
Свои 5 копеек:
В задаче E можно обойтись обычным хэшиком по одному прайму. Если мысленно склеить все строки подматрицы в одну строку, то найти хеш такой строки не составит проблем. Если предпосчитать хеши с каждой позиции на b элементов влево (где это допустимо) и предпосчитать все степени прайма до C * D, то дальнейшее решение можно реализовать за O(C * D) и использовать лишь один прайм.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Хорошая идея.
    • 13 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится
      Прочитал разбор задачи C. Очень жаль, что в ней заходили сеты и бипоиски. Задача действительно неплохая.
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
D ещё можно c N префикс-функциями, правда памяти N2
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

B: сразу юзал oeis и вспомнил недвание топики на кф про умножение long long.

C: для меня сразу было очевидно решать влоб, проверяя калдовством с битами. Сразу пришла в голову мысль сбросить последние нули простым (while(!(a&1)) a>>=1), а потом проверка (a&(a+1)==0). Долго думать не стал, это и закодил. Правда тут косяк..while работал бесконечно - нужно было проверить a на равенство 0.

D: понятно хэши, понятно с e-maxx :)

E: тут поинтереснее. Вначале начал кодить хэши по строчкам и по столбцам и потом объединять. Когда в конец запутался пришла другая мысль. Считаем хэши для прямоугольников от (0;0) до (i,j), по формуле (h[i][j] = (s[i][j] - 'a' + 1) * p_pow[i*c+j]+h[i][j-1]+h[i-1][j]-h[i-1][j-1];) Тут как и в хэшах со строчкой каждому элементу матрицы свой множитель (p^( i*c+j )). А теперь совсем просто:

если hh*p_pow[(i-a+1)*c+(j-b+1)]==aa, где hh - хэш данной подматрицы ( hh+= (s1[i][j] - 'a' + 1) * p_pow[i*c+j]; ), aa - хэш рассматриваемой подматрицы заканчивающийся позицией (i,j). 

  p_pow[(i-a+1)*c+(j-b+1)] - это та разница, как и в хэшах по строке, которая компенсирует сдвиг.

13 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится
Там в Е у меня зашло решение, где я брал хеши для каждой строки и потом чисто по строкам сравнивал. То ест решение у меня было (c-a)*(d-b)*a. Понятно, что на рандомных тестах там всё красиво, но если первая матрица 500*500, а вторая 1000*1000 и везде только символы "а", то моё решение работает на довольно быстрой машине больше 10 секунд. Я поставил проверку на тесты, где только один символ встречается, но даже не надеялся, что пройдёт. Какого же было моё удивление, когда + увидел. Короче, задача хоть и тривиальная, но довольно интересная; единственная недоработка - вик-тесты.