Problem Link
Practice
Contest
Author:Noszály Áron
Tester:Misha Chorniy
Editorialist:Bhuvnesh Jain
Difficulty
MEDIUM
Prerequisites
Factroisation, Combinatorics
Problem
You are given $N$ workers and each of them has a deadline to complete the work, given by $d_i$ for $i^{th}$ worker. Each worker completes the work in $1$ day and on each day at most $1$ worker can work. You need to decide to the array containing the deadline for every worker such that the number of ways in which the workers can decide to work is $C$ and $d_n$ is minimised. Also, the array of deadlines should be sorted.
Explanation
Before proceeding towards the solution, we need to find the number of ways in which workers can decide to work for a given array $d_1 ≤ d_2 ≤ \cdots ≤ d_n$.
Consider the case for $n ≤ 3$. Let $d_1 = x, d_2 = y, d_3 = z$. We have the following dynammic programming solution
$$dp[x] = x$$
$$dp[x][y] = dp[x] * (y - x) + dp[x-1] * x = xy - x^2 + x^2 - x$$
$$dp[x][y] = xy - x = (y-1) * dp[x]$$
$$dp[x][y][z] = dp[x][y] * (z - y) + dp[x][y-1] * (y - x) + dp[x-1][y-1] * x$$
$$dp[x][y][z] = (xy - x)(z - y) + (xy - 2x)(y - x) + (xy - 2x - y + 2)x$$
$$dp[x][y][z] = (xyz - xz - 2xy + 2x) = (z - 2) * (xy - x)$$
$$dp[x][y][z] = (z - 2) * dp[x][y]$$
Using the above observations, it is clear that number of ways is $\prod_{i=1}^{i=n} {(d_i - i + 1)}$. We can even prove it combinatorially. The first person has $d_1$ choices, the second one has $(d_2 - 1)$ choices and so on. By the principle of multiplication, the number of ways comes out to be same.
Note the above solution clearly points out that $d_i >= i$. Thus for $C = 1$, the array is $(1, 2, 3, 4, \cdots)$.
Thus, the problem now reduces to finding an array $d_1 ≤ d_2 ≤ \cdots ≤ d_n$ such that $\prod_{i=1}^{i=n} {(d_i - i + 1)} = C$ and $d_n$ is minimised.
Instead of finding $d_1, d_2 \cdots d_n$, we will find sorted array, $d_1, (d_2-1), \cdots, (d_n-n+1)$, such that product of this sequence is $C$ and later add back $(i - 1)$ to every term to ensure that sequence is increasing.
Subtask 1: N ≤ 10, C ≤ 100
We can use dynamic programming based solution for this subtask. Let $dp[N][C]$ denote the minimised value of $d_n$ for which the sequence $d_1, d_2, \cdots, d_n$ has number of ways as $C$. The transitions are simple. Let $dp[N][C] = x$. So, we need to find the minimum value for the sequence with $(N - 1)$ terms and product as $(C/x)$. The possible candidates are the divisors of $(C/x)$. So, we try all possible candidates and update our answer whether or not it is possible to form an array with the tried candidate. Once, the dynamic programming table is built, we can simply backtrack it to print the answer.
The time compleixty of the above approach is $O(N * {\sigma_{0}{(C)}}^2)$, where $\sigma_{0}{(C)}$ denotes the number of divisors of $C$.
For details, you can refer to author's solution for the above approach.
Subtask 2, 3: N ≤ ${10}^6$, C ≤ ${10}^9$
We may see that for optimal answer, the sequence $d_1, (d_2-1), \cdots, (d_n-n+1)$, looks like the following for large $n$:
[zero or more numbers greater than 1] [bunch of ones] [zeros or more numbers greater than 1]
Outline of proof for above claim: Basically we want to show that if we have a solution that is not in the above form, then there's a solution of the above form which has the same last element. We achieve this by moving the blocks of non $1$ elements as a unit, in this part, we will use the monotonicity of array $d$ as an argument to show that the blocks are indeed movable and don't break anything.
The above form is important because increasing $N$ actually just pushes more ones into the middle (if there were a better way to distribute the numbers we would have used it earlier). So to solve, we calculate the optimal sequence for smaller $N$ and then extend the "bunch of ones" in the middle.
In the worst case the above method's complexity is $O(N + (\text{number of prime factors of C}) * {\sigma_{0}{(C)}}^2)$. Because the number of prime factors in the range of ${10}^9$ is $30$ in the worst case and the number of divisors is $1000$ in the worst case, this gives around $3 * {10}^7$ operations per test case.
For more details, you can refer to the setter's or tester's solution below.
Editorialist Solution: Based on solutions by contestants in the contest (Greedy approach)
We will first store all the factors of $C$. Now, we traverse the factors one by one and check if we can form an array $d_1, (d_2-1), \cdots, (d_n-n+1)$, such that the last element is given factor. Is yes, we simply update the answer. Below is the pseudo-code for checking whether we can find an array with the last element as given factor $x$.
# facts store the factors of C.
# facts[idx] = x
def check(idx):
ptr = n
prod = c
while ptr > 0:
while prod % facts[idx] != 0
idx -= 1
prod /= facts[idx]
ans[ptr] = facts[idx] + ptr - 1
ptr -= 1
if idx != len(facts)-1 and facts[idx] == (facts[idx+1] - 1):
idx += 1
if idx == 0 or prod == 1:
break
return (prod == 1)
Let us analyse the above pseudo-code. We first try to greedily find the first largest factor of the remaining product. At first step it will be $facts[idx] = x$, the number we want to check. Since in final array we want $d_{(i-1)} ≤ d_i$ and we are finding array $(d_i - i + 1)$, the previous term can now contain a possible larger factor only if it is greater than the previous factor by $1$. The last condition just checks that if the product has become 1, then we know the trivial answer or if the factor to be considered is $1$, the product will remain same. Below is an example iteration of the above for $N = 8$ and $C = 36$. Let the factor to be checked is $x = 2$.
$$\text{facts} = {1, 2, 3, 4, 6, 9, 12, 18, 36}$$
$$\text{Step 1} = {\cdots, 2}$$
$$\text{Step 2} = {\cdots, 3, 2}$$
$$\text{Step 3} = {\cdots, 3, 3, 2}$$
$$\text{Step 4} = {\cdots, 2, 3, 3, 2}$$
Since the prod now becomes $1$ we break. To build the required array we add the offsets $(i - 1)$ to the array.
Thus, required array is $(1, 2, 3, 4, 6, 8, 9, 9)$. Note that this may or may not be the optimal solution. It just shows how we check if a given factor can form the series if it is the last term in the sequence.
The time complexity of the above approach will be $O(\sigma_{0}{(C)} * \log{C} + N)$. This is because, for every factor, the checking will take $O(\log{C})$ step in the worst case as "prod" variable will decrease by a factor of atleast $2$ in each iteration. The second term, $O(N)$, is for building the complete sequence containing the initial trivial part of $(1, 2, 3, \cdots)$ and printing the answer. The space complexity will be $O(N + sqrt(C))$.
Once, you are clear with the above idea, you can see the editorialist implementation below for help.
Feel free to share your approach, if it was somewhat different.
Time Complexity
$O(N + (\text{number of prime factors of C}) * {\sigma_{0}{(C)}}^2)$ or $O(\sigma_{0}{(C)} * \log{C} + N)$
Space Complexity
$O(sqrt(C) + 1000 * sqrt(C) + N)$, where $1000$ denotes the value of small $N$ used by author to solve problem by dynamic programming.
AUTHOR'S AND TESTER'S SOLUTIONS:
Author's solution can be found here.
Tester's solution can be found here.
Editorialist's solution can be found here.