793. 阶乘函数后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,找出多少个非负整数x ,有 f(x) = K 的性质。

示例 1:
输入:K = 0
输出:5
解释: 0!, 1!, 2!, 3!, and 4! 均符合 K = 0 的条件。

示例 2:
输入:K = 5
输出:0
解释:没有匹配到这样的 x!,符合K = 5 的条件。
注意:

K是范围在 [0, 10^9] 的整数。
解题思路
我们知道随着n增大,阶乘0的个数是单调递增的。那么我们利用5的阶乘求出有几个0.
剩下的就可以用二分查找找到0的个数等于k的左右边界,然后右边界减左边界+1就是问题所求
二分查找的下限为0,上限由k决定。k的最大值为10^9,则int的最大值会溢出,应该选择long的最大值
图片说明

class Solution {
    public int preimageSizeFZF(int K) {
        //trailingZeroes(n) == K 的右侧边界-左侧边界加上1.就是中间有多少等于k
        return (int)(right_bound(K)-left_bound(K))+1;
    }
    public long trailingZeroes(long n){

        long res=0;
        for(long d=n;d/5>0;d=d/5){
            res+=d/5;
        }
        return res;
    }
    ///* 搜索 trailingZeroes(n) == K 的左侧边界 */
    public long left_bound(int target){
        long li=0;
        long ri=Long.MAX_VALUE;
        while(li<ri){
            long mid=(ri-li)/2+li;
            if(trailingZeroes(mid)<target){
                li=mid+1;
            }
            else{//大于等于一定不是左边界(前一个不一定,所以不能mid-1)
                ri=mid;
            }
        }
        return li;
    }
    //最后让li指向最右侧边界
    public long right_bound(int target){
        long li=0;
        long ri=Long.MAX_VALUE;
        while(li < ri){
            long mid=(ri-li)/2+li;
            if(trailingZeroes(mid)>target){
                ri=mid;
            }else{//li需要指向>k的,所以<=k,则直接右移li
                li=mid+1;
            }
        }
        return li-1;
    }
}