Маршруты с круглой суммой

тема: Префиксные суммы · уровень: продвинутый

Условие

В городе Ровномайске вдоль одной длинной улицы стоят датчики. Каждый датчик за день собрал некоторое число «единиц шума».

Мэр любит круглые числа: маршрут подряд идущих кварталов считается удачным, если суммарный шум на этом отрезке делится на число k без остатка.

Найдите, сколько существует удачных маршрутов (то есть сколько подотрезков массива имеют сумму, кратную k).

Важно: суммы могут быть очень большими (до значений, не вмещающихся в 32-битный тип; как на олимпиадах). В Python это не проблема.

Формат ввода

В первой строке записаны два целых числа n и k. Во второй строке записаны n целых чисел a1, a2, ..., an — шум по кварталам.

Формат вывода

Выведите одно целое число — количество подотрезков, сумма на которых делится на k.

Ограничения

Пример

Ввод:

5 3
1 2 3 4 1

Вывод:

4

Как решать — идея подхода

Приём: Префиксные суммы + подсчёт остатков (хеш-таблица)

Ключевое наблюдение: сумма на отрезке [l..r] равна pref[r] - pref[l-1], где pref[i] — сумма первых i элементов. Эта сумма делится на k тогда и только тогда, когда pref[r] % k == pref[l-1] % k. То есть каждый «удачный маршрут» соответствует паре префиксов с одинаковым остатком.

Почему работает приём: вместо перебора всех O(n^2) подотрезков мы идём слева направо и считаем, сколько раз уже встречался текущий остаток. Каждый прошлый такой остаток даёт новый подотрезок, заканчивающийся в текущей позиции.

План:

Сложность: O(n) по времени и O(min(n, k)) по памяти (храним только встреченные остатки; удобно через dict, особенно когда k большой).

Частая ошибка: забыть про cnt[0] = 1 — тогда не посчитаются отрезки, начинающиеся с первого элемента.

Решить задачу с автопроверкой на Python →

Куда дальше