阶乘函数后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] 的整数。

解析:

1、首先弄清楚阶乘后面K个零的问题。
阶乘后面有K个0,可以将阶乘函数(K个25)(末尾不含0的部分),因为2出现的次数要比5出现的次数多,所以考虑阶乘后面K个0的问题实质上就是阶乘可以分离出K个质因数5。
比如:
5! 可以分理出一个5—— 后面一个0;
10! 可以分离出两个5——5中一个,10中一个;
20! 可以分离出四个5——5,10,15,20中各一个; 21!,22!,23!,24!后面都只有4个0
25! 可以分离出六个5—— 5,10,15,20中各一个,25中两个
观察以上数据,我们可以一下几条结论:
1、阶乘末尾0的个数与阶乘可以分离“质因数5”的个数相等
2、阶乘函数X!末尾有K个零,这样的X可能有五个,可能没有

2、优化算法
关于“阶乘后面零的个数”,我们采用“减治法”可以将算法时间复杂度优化到log(n).
关于“阶乘后面K个零的问题”,这里我们要利用搜索来找到一个值,它的阶乘后面有K个零,当然也存在找不到的可能。此题利用暴力搜索总的时间复杂度是nlog(n),好像也不大,最大的数据跑了160ms时间并不是很长,但是系统会显示超时。我这里花了好长时间尝试,最后将暴力改成了二分搜索效率大大提高,最大数据跑了8ms.总的时间复杂度是log(n)*log(n)。

注解代码如下:
int fun(long long x){      //返回x!后面零的个数
    int count=0;
    int i=1;
    while(x>=pow(5,i)){
        count+=x/pow(5,i);
        i++;
    }
    return count;
}

int preimageSizeFZF(int K){
    long long start=1,end=K+1;            
     //(5*start)!末尾至少含有1个0,(5*end)!末尾至少含有K+1个0。如果存在(5*a)!后面有K个0,那么X的取值为 5*a,5*a+1,5*a+2,5*a+3,5*a+4,否则X的取值为空。
    while(start<end){                                //利用二分法确定确定a的值                 
        long long a=start+(end-start)/2;
      // printf("%d     %d",a,fun(5*a));
        if(fun(5*a)==K)
            return 5;
        else if(fun(5*a)>K){
            if(a==end)        //说明找不到满足调节的a
                return 0;
            else
                end=a;
        }else if(fun(5*a)<K){
            if(a==start)     //说明找不到满足调节的a
                return 0;
            else
                start=a;
        }
    }
    if(K==0)             //阶乘后面没有0,上面二分法没有处理的
        return 5;
    //else               这个注释掉可能更好理解   
        return 0;
}

感谢您的阅读,祝您学习进步,身心愉快,有用的话别忘了点个赞,有不足的地方还望多多指教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值