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
indicesi
(where1 <= i < n
) satisfy the conditionarr[i - 1] == arr[i]
.
Return the number of good arrays that can be formed.
Since the answer may be very large, return it modulo 10⁹ + 7
.
https://leetcode.com/problems/count-the-number-of-arrays-with-k-matching-adjacent-elements/
Example 1:
Input:
n = 3, m = 2, k = 1
Output:4
Explanation:
- There are 4 good arrays. They are
[1, 1, 2]
,[1, 2, 2]
,[2, 1, 1]
and[2, 2, 1]
.- Hence, the answer is 4.
Example 2:
Input:
n = 4, m = 2, k = 2
Output:6
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.
Example 3:
Input:
n = 5, m = 2, k = 0
Output:2
Explanation:
- The good arrays are
[1, 2, 1, 2, 1]
and[2, 1, 2, 1, 2]
. Hence, the answer is 2.
Constraints:
1 <= n <= 10⁵
1 <= m <= 10⁵
0 <= k <= n - 1
Test Cases
1 | class Solution: |
1 | import pytest |
Thoughts
全都是数论知识。
首先 n 个位置中,有且只有 k 个位置的数跟其左边的数相等,显然除了 i = 0
之外其他的都可以,相当于从 n - 1
个位置中任选 k 个,一共有 个选择。
把选中的 k 个位置先拿掉,剩下 n - k
个,这些位置填入的数字都不能与其左边的数字相等。第一个位置有 m 个选择,之后的每个位置都有 m - 1
个选择,一共有 m * (m - 1) ** (n - k - 1)
个选择。
上边两个事件相互独立,所以乘积就是总的选择数,即可以构造出的 good array 总数:
其中 可以用 3266. Final Array State After K Multiplication Operations II 中提到的二分法幂运算。
组合数 就有点儿棘手,因为 ,但是模运算不支持除法。
这里需要用到模逆元(Modular multiplicative inverse)。如果要计算 (x / a) % p
,可以先求 a 对于 p 的模逆元 b((a * b) % p = 1
),再计算 (x * b) % p
即可。
求 a 对于 p(本题中 p = 10⁹ + 7
是个质数)的模逆元,可以用费马小定理(Fermat’s little theorem),易知 a ** (p - 2) % MOD
是 a 的逆元(因为 )。
可以事先把最大值(10⁵)以内所有数的阶乘,以及每个阶乘的模逆元都计算好存下来,用的时候直接查表即可。
求模逆元的时间复杂度是 O(log p)
。
对于连续自然数的阶乘,并不用每个结果都求模逆元,可以对最后一个结果求模逆元,然后倒着推算回去,因为:
不考虑提前缓存所有的阶乘与阶乘的模逆元,时间复杂度为 O(n)
(幂运算是 O(log n)
,阶乘是 O(n)
,阶乘的模逆元是 O(log (10⁹ + 7))
可以认为是常数。
Code
1 | MAX = 100_000 |