Problem
You are given three integers n
, m
, k
. A good array arr
of size n
is defined as follows:
Each element in arr
is in the inclusive range [1, m]
.
Exactly k
indices i (where 1 <= i < n)
satisfy the condition arr[i - 1] == arr[i]
.
Return the number of good arrays that can be formed.
Since the answer may be very large, return it modulo 109 + 7
.
Examples
Example 1
1 | Input :n = 3, m = 2, k = 1 |
Explain: In the array, it should choose element from [1,2]. And there should be 1(k) pair of adjacent elements has the same value. The length of the array is 3. They are[1,1,2],[1,2,2],[2,2,1],[2,1,1]
Example 2
1 | Input: n = 4, m = 2, k = 2 |
Explanation:
The good arrays are [1, 1, 1, 2], [1, 1, 2, 2], [1, 2, 2, 2], [2, 1, 1, 1], [2, 2, 1, 1] and [2, 2, 2, 1].
Hence, the answer is 6.
Intuition
Emmmmmm, personally, it is impossible to enumerate all the possible arrays and check that they are ‘good’ or not. That makes time complexity blow up.(Btw, what is its complexity?) The best way to solve it is gorgeous math. Nani? We are going to solve this question with some black magic!
In array of length n
, there are n-1
paris with adjacent element. Among n-1
pairs, k
pairs must consist equal adjacent element and remaining n-1-k
pairs must consist different adjacent elements. We can treat these n−1−k differing adjacent as partitions or bars(the stick.. not drinking one), which divide the array into n−k contiguous segments(stars), where each segment contains identical values. Yes! That’s is a altered combinatorial number question which most of Chinese senior high school student can tackle. If you are at sea pls clickBars and Stars.
- Among the
n-1
positions between array elements, we choosen−1−k
to place the partitions. This can be done in $\binom{n-1}{n-1-k} =\binom{n-1}{k}$ ways. - The first segment can take any of the m values.
- Every subsegment (there are
n−k−1
such subsegment) must differ from the previous’s value, meaning each of them hasm−1
possible choices. Hence we have $(m-1)^{n-k-1}$.
Sweeeeet, now we got the number $(n-1) * m *((m-1)^{n-k-1})$
U R highly recommended to read Binary Exponentiation and module-inverse OR (there is a better Chinese version)乘法逆元 before coding. Looking back, I’m thankful I wrestled with discrete math.
COOOOOOOOOOOOOOOOOOOOOOOOOOding
1 | const int MOD = 1e9 + 7; |
If you are a python guy…. you can also…
1 | result = math.comb(n-1, k) * m * pow(m-1, n-k-1, MOD) % MOD |
Now which is the best language in the world?