Подсказка № 1:
Подумайте, как вы можете использовать оператор MODULUS, чтобы помочь вам. Изначально у вас есть N чисел, скажем, N равно 5.
Таким образом, мы можем сохранить остатки для каждого номера (то есть сохранить 0 MOD 3, 1 MOD 3, 2 MOD 3 и т. Д.):
a[0] = 0
a[1] = 1
a[2] = 2
a[3] = 0
a[4] = 1
a[5] = 2
Каждый раз, когда вы увеличиваете диапазон чисел между A и B, вам действительно нужно хранить только 0, 1 или 2 в массиве. Например, если мы увеличиваем 2, то новым числом будет 3. Это теперь делится на 3, поэтому мы храним 0 в массиве. Таким образом, в случаях, когда у нас есть 0 и мы увеличиваем, мы храним 1, если у нас есть 1, мы храним 2, а если у нас 2, мы храним 0.
Эта оптимизация устраняет необходимость в любом делении, кроме начального шага. Деление - это очень дорогая операция, поэтому мы хотим устранить ее там, где можем.
Таким образом, после увеличения от 0 до 5 массив будет выглядеть так:
a[0] = 1
a[1] = 2
a[2] = 0
a[3] = 1
a[4] = 2
a[5] = 0
Количество чисел между A и B, которые делятся на 3, - это просто количество элементов, которые имеют 0 (в данном случае 2).
Теперь вам нужно подумать о том, как эффективно запросить диапазон от A до B, чтобы найти количество чисел, делимых на 3.
Подсказка № 2:
Чтобы выяснить, сколько чисел в интервале [A, B] делится на 3, можно использовать одну структуру алгоритма / данных - дерево сегментов. Читайте об этом здесь . Это выгодно для вас тем, что теперь вы можете очень быстро вычислить количество чисел, делимых на 3 для любого такого интервала [A, B], вместо того, чтобы перебирать массив и считать их.