Редакция для Кратные на отрезке
Submitting an official solution before solving the problem yourself is a bannable offence.
Разбор задачи «Кратные на отрезке»
1. Идея
Для каждого элемента нужно понять только одно: подходит он или нет, то есть делится ли a_i на d.
После этого задача превращается в такую:
- есть массив из
0и1, 1означает, что код кратенd,- для каждого запроса
[l, r]надо найти сумму на этом отрезке.
А сумму на отрезке очень удобно считать с помощью префиксных сумм.
2. Наблюдения
Если создать массив b, где:
b[i] = 1, еслиa_i % d == 0,b[i] = 0иначе,
то ответ на запрос — это просто количество единиц на отрезке [l, r].
Теперь введём массив префиксных сумм pref, где pref[i] — количество подходящих элементов среди первых i элементов.
Тогда:
pref[0] = 0,pref[i] = pref[i - 1] + b[i].
Количество подходящих элементов на отрезке [l, r] равно:
pref[r] - pref[l - 1].
Это стандартная идея: из суммы на префиксе до r вычитаем сумму на префиксе до l - 1.
3. Алгоритм
- Считываем
nиd. - Идём по массиву кодов и сразу строим префиксный массив
pref.pref[0] = 0- для каждого
iот1доn:- если текущий код кратен
d, добавляем1, - иначе добавляем
0.
- если текущий код кратен
- Считываем число запросов
q. - Для каждого запроса
l, rвыводим:pref[r] - pref[l - 1].
4. Почему это работает
Пусть pref[i] — число элементов, кратных d, среди позиций от 1 до i.
Тогда:
pref[r]считает все подходящие элементы на отрезке от1доr,pref[l - 1]считает все подходящие элементы на отрезке от1доl - 1.
Если вычесть второе из первого, останутся только элементы с позиций от l до r.
Значит, pref[r] - pref[l - 1] действительно равно количеству кодов, кратных d, на отрезке [l, r].
5. Сложность
Построение префиксного массива занимает O(n).
Каждый запрос обрабатывается за O(1).
Итоговая сложность:
O(n + q)
Память:
O(n)
Это хорошо укладывается в ограничения до 2 * 10^5.
6. Код на C++17
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
long long d;
cin >> n >> d;
vector<int> pref(n + 1, 0);
for (int i = 1; i <= n; i++) {
long long x;
cin >> x;
pref[i] = pref[i - 1] + (x % d == 0 ? 1 : 0);
}
int q;
cin >> q;
for (int i = 0; i < q; i++) {
int l, r;
cin >> l >> r;
cout << pref[r] - pref[l - 1] << '\n';
}
return 0;
}
7. Код на Python 3
n, d = map(int, input().split())
a = list(map(int, input().split()))
pref = [0] * (n + 1)
for i in range(1, n + 1):
pref[i] = pref[i - 1] + (1 if a[i - 1] % d == 0 else 0)
q = int(input())
for _ in range(q):
l, r = map(int, input().split())
print(pref[r] - pref[l - 1])
Комментарии