Генерація колізій

Перегляд у форматі PDF

Надіслати розв'язок

Бали: 4,00 (partial)
Time limit: 1.0s
Memory limit: 256M
Input: stdin
Output: stdout

Problem type

Напишіть програму, яка згенерує багато (беззмістовних з точки зору природньої мови) string-ів однакової довжини, котрі мають однаковий hash, якщо рахувати його за правилами типу String мови Java, тобто ~s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-2]*31+s[n-1]~ (де ~n~ – довжина рядка; інакше кажучи, обчислення hash-коду починається з числа 0, далі на кожному кроці спочатку старе значення домножається на 31, потім до нього додається ASCII-код чергової літери слова); обчислення hash-коду відбувається у знаковому 32-бітовому типі, з переповненнями.

Вхідні дані

В одному рядку через пропуски (пробіли) записані: спочатку потрібна однакова довжина рядків ~L~ (~8\leqslant L\leqslant 32~); потім кількість блоків ~K~ (~1\leqslant K\leqslant 2017~), таких, що всередині кожного блоку всі string-и повинні мати однаковий hash-код, а для різних блоків різні; потім кількість різних рядків всередині кожного з цих блоків ~N~ (~2\leqslant N\leqslant 2017~).

~K~ та ~N~ не будуть великими одночасно; гарантовано, що сумарний розмір всіх рядків результату не перевищуватиме одного мегабайту.

Результати

Слід вивести ~K\cdot N~ рядків, кожен з яких містить унікальний (у межах поточного запуску програми) string довжиною рівно ~L~, причому всі рядки з 1-го по ~N~-й повинні мати однаковий hash-код; якщо ~K\geqslant 2~, то всі рядки з ~(N+1)~-го по ~(2N)~-й повинні мати однаковий між собою, але відмінний від рядків з 1-го по ~N~-й, hash-код, і так далі. (В цьому поясненні вважаємо, що нумерація починається з одиниці). Таким чином, рядки з 1-го по ~N~-ий утворюватимуть один блок, рядки з ~(N+1)~-го по ~(2N)~-й (якщо ~K\geqslant 2~, тобто якщо їх взагалі треба виводити) утворюватимуть ще один блок, і так далі. Розділяти ці блоки якимись додатковими роздільниками не треба.

Символи рядків, які виводить Ваша програма, не зобов'язані бути буквами, але зобов'язані мати ASCII-коди від 33 до 126 (обидві межі включно).

Приклади

Вхід

8 3 3

Результат

BBBBBBBB
AaBBBBBB
BAaBBBBB
FFFFFFFF
EeFFFFFF
FEeFFFFF
SSSSSSSS
RrSSSSSS
SRrSSSSS

Примітки

У цій задачі можуть бути різні правильні відповіді. Ваша програма повинна виводити будь-яку одну правильну.

Поки що якість автоматичної перевірки цієї задачі вивірена не досить ретельно, в разі обґрунтованих сумнівів щодо правильності перевірки звертайтеся.

Головна ідея: якщо у двох сусідніх символах лівий збільшити на 1, а правий зменшити на 31 (у смислі відповідного збільшення/зменшення ASCII-кодів цих символів), то hash-код (обчислений саме за цією hash-функцією! це важливо!) лишиться незмінним. Однак, для проходження всіх тестів цієї задачі потрібно трошки посилити цю ідею:

  • помітити, що такі збільшення та зменшення можна застосувати також і одночасно в різних парах сусідніх символів;
  • помітити, що абсолютно те саме буде також і при збільшенні лівого на 2 та зменшенні правого на 62, або зменшенні лівого на 1 та збільшенні правого на 31, або зменшенні лівого на 2 та збільшенні правого на 62. (Забезпечити, щоб усі перелічені варіанти давали символи в проміжку ASCII-кодів від 33 до 126, неможливо; але це й не треба: досить забезпечити в тій самій парі сусідніх символів 2–3 зсуви (3–4 значення).)

Наприклад, усі «слова» з переліку

  • 3&&
  • 2E&
  • 1d&
  • 3%E
  • 2DE
  • 1cE
  • 3$d
  • 2Cd
  • 1bd

мають однаковий Java-hash-код 50227. Їх вдалося зробити аж 9, при довжині всього 3 та дотримавшись обмеження «ASCII-коди всіх символів від 33 до 126».


Коментарі

Please read the guidelines before commenting.


Ще немає коментарів.