[LC793]阶乘函数后 K 个零

题目描述

f(x) 是 x! 末尾是 0 的数量。(回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 )
例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 ;而 f(11) = 2 ,因为 11!= 39916800 末端有 2 个 0 。
给定 k,找出返回能满足 f(x) = k 的非负整数 x 的数量。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/preimage-size-of-factorial-zeroes-function
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

本体并非给定一个n!,来求解最后n!有多少个0,而是问满足给定一个k,有多少个x!可以满足X!最后的0的个数为k。
在【172. 阶乘后的零】中我们学会了使用容斥原理来求解n!后面的0的个数,那么在本题中就可以使用这样一种思路:

  • 我们记函数maxValueSatisfyZeroCount(k)能求解出满足阶乘后结果中末尾0的个数小于等于k的最大的数为多少
    • 比如1!, 2!, 3!, 4!都满足最后的0的个数为小于等于0个,那么这个maxValueSatisfyZeroCount(0)会返回4
  • 那么本题的解可以转化为maxValueSatisfyZeroCount(k) - maxValueSatisfyZeroCount(k-1)
  • 我们如何寻找这个符合条件的最大值呢?
    • 最朴素的想法是我们从0到n遍历所有数,使用容斥原理对每个数进行求解,知道找到最大的符合条件的值为止。
    • 实际上我们可以用二分查找来加速这一过程,因为n!后零的数量与n的增长实际上是呈单调关系的,满足二分查找的基本使用条件。

代码

golang
func preimageSizeFZF(k int) int {
	if k <= 1 {
		return 5
	}
	return maxValueSatisfyZeroCount(k) - maxValueSatisfyZeroCount(k-1)
}

func maxValueSatisfyZeroCount(zeroTarget int) int {
	l, r := 0, int(10e10)
	for l < r {
		mid := (l + r + 1) / 2
		if countZeros(mid) <= zeroTarget { //we shrink left to find maxValue
			l = mid
		} else {
			r = mid - 1
		}
	}
	return l
}

func countZeros(value int) int {
	zeros := 0
	for value != 0 {
		zeros += value / 5
		value /= 5
	}
	return zeros
}
posted @ 2022-08-28 16:55  XinStar  阅读(33)  评论(0编辑  收藏  举报