Use this to learn the idea, then write your own version.
12 3456 7from bisect import bisect_left, bisect_right8from typing import Generic, List, TypeVar9 10T = TypeVar("T", bound=List[int])11 12NOT_FOUND = -113 14 15class Finder(Generic[T]):16 def __init__(self, values: T = [], offset: int = 0) -> None:17 self.values = values18 self.offset = offset19 self.indexes = []20 21 if values:22 self.init(values, offset)23 24 def init(self, values: T, offset: int = 0) -> None:25 self.values = values26 self.offset = offset27 28 if not self.values:29 return None30 31 value_min, value_max = min(values), max(values)32 inf = offset + 10**1233 assert offset <= value_min and value_max < inf34 self.indexes = [[] for _ in range(value_max - offset + 1)]35 36 for i in range(len(self.values)):37 self.find_indexes(self.values[i]).append(i)38 39 def append_list(self, values: T) -> None:40 for value in values:41 self.append(value)42 43 def append(self, value: int) -> None:44 assert self.offset <= value45 46 if len(self.indexes) <= value - self.offset:47 self.indexes.extend(48 [[] for _ in range(value - self.offset - len(self.indexes) + 1)]49 )50 self.find_indexes(value).append(self.get_size())51 self.values.append(value)52 53 def pop(self) -> int | None:54 if self.is_empty():55 return None56 57 self.find_indexes(self.values[-1]).pop()58 59 return self.values.pop()60 61 def clear(self) -> None:62 self.values.clear()63 self.indexes.clear()64 65 def find_indexes(self, value: int) -> List[int]:66 if self._validate_range(value):67 return [NOT_FOUND]68 69 return self.indexes[value - self.offset]70 71 def find_index(self, value: int, right: int) -> int:72 if self._validate_range(value):73 return NOT_FOUND74 75 indexes = self.find_indexes(value)76 77 return NOT_FOUND if len(indexes) <= right else indexes[right]78 79 def find_next_index(self, index: int, value: int) -> int:80 if self._validate_range(value):81 return NOT_FOUND82 83 indexes = self.find_indexes(value)84 pos = bisect_right(indexes, index)85 86 return NOT_FOUND if pos == len(indexes) else indexes[pos]87 88 def find_prev_index(self, index: int, value: int) -> int:89 if self._validate_range(value):90 return NOT_FOUND91 92 indexes = self.find_indexes(value)93 pos = bisect_left(indexes, index)94 95 return NOT_FOUND if pos == 0 else indexes[pos - 1]96 97 def find_ceil_index(self, index: int, value: int) -> int:98 return self.find_next_index(index - 1, value)99 100 def find_floor_index(self, index: int, value: int) -> int:101 return self.find_prev_index(index + 1, value)102 103 def find_cycle_next_index(self, index: int, value: int) -> int:104 if self._validate_range(value):105 return NOT_FOUND106 107 next_index = self.find_next_index(index, value)108 109 if next_index == NOT_FOUND:110 next_index = self.find_next_index(-1, value)111 112 return next_index113 114 def find_cycle_prev_index(self, index: int, value: int) -> int:115 if self._validate_range(value):116 return NOT_FOUND117 118 prev_index = self.find_prev_index(index, value)119 120 if prev_index == NOT_FOUND:121 prev_index = self.find_prev_index(self.get_size(), value)122 123 return prev_index124 125 def find_cycle_ceil_index(self, index: int, value: int) -> int:126 return self.find_cycle_next_index(index - 1, value)127 128 def find_cycle_floor_index(self, index: int, value: int) -> int:129 return self.find_cycle_prev_index(index + 1, value)130 131 def count_values_in_ranges(self, value: int, left: int, right: int) -> int:132 return self._count_value(right, value) - self._count_value(left - 1, value)133 134 def is_empty(self) -> bool:135 return not self.values136 137 def get_size(self) -> int:138 return len(self.values)139 140 def _validate_range(self, value: int) -> bool:141 return value < self.offset or self.offset + len(self.indexes) <= value142 143 def _count_value(self, right: int, value: int) -> int:144 if self._validate_range(value):145 return 0146 147 indexes = self.find_indexes(value)148 149 return bisect_right(indexes, right)150 151 152def main():153 import sys154 from collections import defaultdict155 from itertools import accumulate156 157 input = sys.stdin.readline158 159 n, m = map(int, input().split())160 a = list(map(int, input().split()))161 acc = list(accumulate(a + a, initial=0))162 d = defaultdict(int)163 164 165 b = [acc_i % m for acc_i in acc]166 f = Finder(b)167 ans = 0168 169 170 for j in range(n):171 count = f.count_values_in_ranges(b[j], j + 1, j + n - 1)172 ans += count173 174 print(ans)175 176 177if __name__ == "__main__":178 main()179