LeetCode 793. 阶乘函数后K个零--找数据规律+二分

67 篇文章 0 订阅
15 篇文章 0 订阅
  1. 阶乘函数后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] 的整数。

题解:

因为python自带大数运输,我们先用python打印前50个结果如下,左边为数字对应的阶乘,右边为尾数0的个数:

0 0
1 0
2 0
3 0
4 0
5 1
6 1
7 1
8 1
9 1
10 2
11 2
12 2
13 2
14 2
15 3
16 3
17 3
18 3
19 3
20 4
21 4
22 4
23 4
24 4
25 6
26 6
27 6
28 6
29 6
30 7
31 7
32 7
33 7
34 7
35 8
36 8
37 8
38 8
39 8
40 9
41 9
42 9
43 9
44 9
45 10
46 10
47 10
48 10
49 10
50 12

不难发现规律,就是尾数为0的个数为K的数字一定有5个,这是为何呢?因为考虑到当相乘为10时,末尾便会产生一个0,而10=2x5,所以我们的目标是在数字x对应的阶乘x!中找有多少个2和多少个5,那么末尾0的个数=min(num0,num5),但是从数字的大小来看,2的个数一定是比5多的,所以问题又简化成了在x!中找有多少个5,也就是把x!一直除5,最终有多少个,便是对应的尾部的0的个数。

那么问题来了,告诉数字x,怎么求x!中5的个数呢?

我们这样分析:
比如给定x=50,50的阶乘如下:

1x2x3x4x5x6x7x8x9x10x11x12x13x14x15x16x17x18x19x20x21x22x23x24x25x26x27x28x29x30x31x32x33x34x35x36x37x38x39x40x41x42x43x44x45x46x47x48x49x50

那么其中和5相关的数字有

5 10 15 20 25 30 35 40 45 50

然后呢,再找上面这些数字能构成多少个5,
5=1x5^1
10=2x5^1
15=3x5^1
20=4x5^1
25=1x5^2
30=6x5^1
35=7x5^1
40=8x5^1
45=9x5^1
50=2x5^2
把右边5的指数全部加起来=1+1+1+1+2+1+1+1+1+2=12和我们上面python打印的结果一致的。

于是,在50的阶乘中,针对5 ^ 1构成的数字个数为50/ 5 ^ 1=10,针对5 ^ 2构成的数字个数为50/ 5 ^ 2=2,所以简化下来的结果就是,针对数字x,末尾0的个数计算方法:

K=x/ 5 ^ 1+x/ 5 ^ 2+x/ 5 ^ 3+......+x/ 5 ^ y
其中5 ^ (y+1)>x

然后再对x进行二分找结果,判断末尾0的个数为K的结果是否存在,存在就返回5,不然返回0.

AC代码

class Solution {
public:
    typedef long long ll;
    ll fun(ll x)
    {
        ll ans=0;
        ll base=5;
        for(int i=1;;i++)
        {
            ans+=(x/base);
            base*=5;
            if(x<base)break;
        }
        return ans;
    }
    int preimageSizeFZF(int K) {
        ll l=0,r=1e18,fin=-1;
        while(l<=r)
        {
            ll mid=(l+r)/2;
            if(fun(mid)>=K)
            {
                r=mid-1;
                fin=mid;
            }
            else l=mid+1;
        }
        return fun(fin)==K?5:0;
    }
};

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值