793. Preimage Size of Factorial Zeroes Function #
Problem #
Let f(x) be the number of zeroes at the end of x!. (Recall that x! = 1 * 2 * 3 * ... * x, and by convention, 0! = 1.)
For example, f(3) = 0 because 3! = 6 has no zeroes at the end, while f(11) = 2 because 11! = 39916800 has 2 zeroes at the end. Given K, find how many non-negative integers x have the property that f(x) = K.
Example 1:
Input: K = 0
Output: 5
Explanation: 0!, 1!, 2!, 3!, and 4! end with K = 0 zeroes.
Example 2:
Input: K = 5
Output: 0
Explanation: There is no x such that x! ends in K = 5 zeroes.
Note:
Kwill be an integer in the range[0, 10^9].
Problem Summary #
f(x) is the number of zeroes at the end of x!. (Recall that x! = 1 * 2 * 3 * … * x, and 0! = 1)
For example, f(3) = 0, because 3! = 6 has no zeroes at the end; while f(11) = 2, because 11! = 39916800 has 2 zeroes at the end. Given K, find how many non-negative integers x have the property that f(x) = K.
Note:
- K is an integer in the range [0, 10^9].
Solution Ideas #
- Given a number K, determine how many n can make the number of trailing 0s in n! equal to K.
- This problem is an enhanced inverse process based on Problem 172. Problem 172 gives
nand asks for the number of trailing 0s. From Problem 172, we know that the number of trailing 0s inn!depends on the number of factors of 5. If there may beKtrailing 0s, thenncan be at most5 * K. Perform binary search in the interval[0, 5* K], and determine the number of trailing 0s ofmid. IfKcan be found, then return 5; if thisKcannot be found, return 0. Why can the answer only be 0 or 5? Because afternincreases by 5, the number of factors of 5 increases by one again, and the trailing zeros can increase by 1 or more (if after adding 5, there are multiple factors of 5, such as 25 or 125, then the trailing zeros may increase by multiple 0s). Therefore, the range interval ofncorresponding to a validKvalue is 5. Conversely, the number ofncorresponding to an invalidKvalue is 0.Kwill jump at the boundary of5^n, so some values cannot be attained. For example, whenntakes values in[0,5),K = 0; whenntakes values in[5,10),K = 1; whenntakes values in[10,15),K = 2; whenntakes values in[15,20),K = 3; whenntakes values in[20,25),K = 4; whenntakes values in[25,30),K = 6, because 25 provides 2 factors of 5, and thus provides 2 zeros, soKcan never take the value 5. That is, whenK = 5, no correspondingncan be found. - This problem can also be solved mathematically. See Solution 2. The inspiration for this solution comes from the fact that the number of trailing 0s in n! equals the total number of factors of 5 among all numbers in [1,n]. Secondly, the result of this problem can only be 0 or 5 (see the analysis in the previous solution). With these two conclusions, we can derive it mathematically. First, n can be represented in base 5 as follows
\[ n = 5^{0} * a_{0} + 5^{1} * a_{1} + 5^{2} * a_{2} + ... + 5^{n} * a_{n}, (a_{n} < 5)\]
In the formula above, the total number of factors of 5 is:
\[ K = \sum_{n=0}^{n} a_{n} * c_{n}\]
This total is exactly K. For different n, the general formula for an differs, so the coefficients representing K also differ. What is the general formula for cn?
\[ c_{n} = 5 * c_{n-1} + 1,c_{0} = 0\] The recurrence above can also derive a general formula (however, the general formula is not applicable for this problem; using the recurrence is more convenient): \[ c_{n} = \frac{5^{n} - 1 }{4} \] Determining whether K can be represented in the form of these two sequences is equivalent to determining whether K can be converted into a mixed-radix number with Cn as the base. At this point, it is transformed into something similar to Problem 483. The code implementation is not difficult; see Solution 2.
Code #
package leetcode
// Solution 1: Binary search
func preimageSizeFZF(K int) int {
low, high := 0, 5*K
for low <= high {
mid := low + (high-low)>>1
k := trailingZeroes(mid)
if k == K {
return 5
} else if k > K {
high = mid - 1
} else {
low = mid + 1
}
}
return 0
}
// Solution 2: Mathematical method
func preimageSizeFZF1(K int) int {
base := 0
for base < K {
base = base*5 + 1
}
for K > 0 {
base = (base - 1) / 5
if K/base == 5 {
return 0
}
K %= base
}
return 5
}