PROBLEM LINK:
Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4
Author: raysh07
Tester: sushil2006
Editorialist: iceknight1093
DIFFICULTY:
Simple
PREREQUISITES:
None
PROBLEM:
You have an array A of length N, with 0 \le A_i \lt M.
You can perform the following operation several times:
- For every index i, replace A_i with (A_i + 1) \bmod M.
Find the minimum possible sum of A after performing this operation several times.
EXPLANATION:
If the operation is performed K times, the element at index i will become (A_i + K) \bmod M.
Observe that this means we’ll only ever need to perform \lt M operations.
This is because, if we perform M operations, the element at index i will become (A_i + M)\bmod M = A_i, so we could just as well not perform the first M operations.
Further, observe that when we perform an operation, every element will increase by 1, except for those elements equal to M-1, which will turn into 0 instead.
Now, suppose we perform K (0 \le K \lt M) operations. Let’s analyze how the array A changes.
- First, consider elements that are “small” - that is, all i for which A_i \lt M - K.
These elements will increase by 1 with each of the K operations made.
So, they will increase by K in total. - Next, let’s look at the “large” elements - that is, A_i \ge M - K.
These elements will increase till they reach M-1, then the next operation will set them to 0, and after that they’ll go back to increasing by 1 every operation.
Since K \lt M, these elements will be reduced to 0 exactly once.
These elements thus increase by one (K-1) times, and reduce by M-1 once.
So, their overall change in value equals (K-1) - (M-1) = (K-M).
The nice thing that can be noticed here, is that the change in an element’s value doesn’t depend too much on its initial value at all: all elements \lt M - K will have the same change, and all elements \ge M - K will have the same change.
So, if there are Y elements in the array that are \lt M - K (and hence (N-Y) elements that are \ge M - K), the overall change in the sum of the array will equal
Our goal now is to compute the value of Y for a fixed K, i.e. the number of elements \lt M - K.
This can be done quickly in several ways:
- Let \text{freq}[x] denote the number of occurrences of x in the array.
Then, the value we’re looking for is \text{freq}[0] + \text{freq}[1] + \ldots + \text{freq}[M-K-1].
This is just a prefix sum of the \text{freq} array, so can be precomputed and then looked up in constant time. - Alternately, you can binary search on A (after sorting it) to find the number of elements \lt M - K, for a complexity of \mathcal{O}(\log N).
In either case, once we fix a value of K, the quantity Y can be computed quickly.
Once Y is known, the change in the sum of A equals Y\cdot K + (N-Y)\cdot (K-M) as derived above.
The answer is then to simply take the minimum change in the sum of A across all values of K, and add it to the initial sum of A.
TIME COMPLEXITY:
\mathcal{O}(N + M) per testcase.
CODE:
Editorialist's code (PyPy3)
for _ in range(int(input())):
n, m = map(int, input().split())
a = list(map(int, input().split()))
freq = [0]*m
for x in a: freq[x] += 1
pref = freq[:]
for i in range(1, m): pref[i] += pref[i-1]
ans = n*m
for k in range(m):
y = 0
if m-k-1 >= 0: y = pref[m-k-1]
ans = min(ans, k*y + (n-y)*(k-m))
print(ans + sum(a))