LeetCode793 阶乘函数后K个零(二分+数论)

博客讨论了LeetCode 793题的解题方法,主要涉及计算阶乘尾部零的个数。文章指出,尾部零的个数由2和5的因子组合决定,由于2的因子数量通常更多,只需关注5的因子。通过计算n!中5的因子个数,并采用二分查找策略,可以确定使得阶乘尾部零数等于K的x值个数。代码实现中包括了`preimageSizeFZF`函数,用于寻找满足条件的x值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:leetcode793

题面

在这里插入图片描述

题目大意

f ( x ) f(x) f(x) 函数是一个求 x ! x! x! 结果尾部 0 个数的函数,现在给你一个 K ,让你求能够找到多少个 x 使得 f ( x ) = K f(x)=K f(x)=K

解题思路

首先,我们考虑这个 f ( x ) f(x) f(x) 函数,不难得出 x ! x! x! 尾部 0 的个数等于该数 2 和 5 因子的组数。分别考虑 x ! x! x! 的 2 因子和 5 因子的个数取最小值即两个因子的组数,显然,对于 n ! n! n! , 5 的因子个数一定小于 2 的因子,所以考虑 5 的因子数。

f ( x ) = ⌊ x 5 ⌋ + ⌊ x 5 2 ⌋ + . . . f(x)=\lfloor \frac{x}{5} \rfloor + \lfloor \frac{x}{5^2} \rfloor + ... f(x)=5x+52x+...
显然, f ( x ) f(x) f(x) 是一个单调递增函数。

转自:推导:传送门

求n!
0的来源 2 * 5 所以一对2和5即可产生一个0,所以0的个数即为min(阶乘中5的个数和2的个数)
又因为是2的倍数的数一定比是5的倍数的数多 所以2的个数一定>=5的个数 所以只需要统计 5 的个数了
例如 5! = 1 * 2 * 3 * 4 * 5
2 2 2 5 一个2和一个5配对出现0 所以5!末尾只有一个零
而在 n = 25 时 可以产生5的有 5 10 15 20 25
即 n/5 = 5个 然鹅 25 = 55 所以少算了一个5
n>=25时,故而需要补上它 因此所有可以产生25的也要加上
即为 n/5 + n/25 然鹅 125 = 5
25 所以又少算了一个5
n>=125时,故而需要补上它 因此所有可以产生125的也要加上
即为 n/5 + n/25 + n/125 然鹅 625 = 5*125 所以又少算了一个5
继续补上…
所以最终为 n/5 + n/25 + n/125 + n/625 + …
即 n/5 + n/5/5 + n/5/5/5 + n/5/5/5/5 + …

我们考虑二分答案即可。当然,本题找到的符合题意的 x 要么有 5 个,要么没有。证明:当找到一个 x 使得: 5 ∣ x !   且   f ( x ) = K 5|x!\ 且\ f(x)=K 5x!  f(x)=K 时,则存在 f ( x + 1 ) = f ( x + 2 ) = f ( x + 3 ) = f ( x + 4 ) = K f(x+1)=f(x+2)=f(x+3)=f(x+4)=K f(x+1)=f(x+2)=f(x+3)=f(x+4)=K 。其实就相当于能够除以 5 后商相同的一定有 5 个。


代码实现

class Solution {
public:
    int preimageSizeFZF(int K) {
        if (K == 0) return 5;
        long long l = 0, r = 5LL * K + 1, mid, s;
        while (l < r) {
            mid = l + (r - l >> 1);
            s = getPrimeSize(mid, 5);
            if (s == K) return 5;
            if (s > K) r = mid;
            else l = mid + 1;
        }
        return 0;
    }
    
    //计算 n! 中 p 的因子个数
    int getPrimeSize(long long n, long long p) {
        long long sz = 0;
        while (n >= p) {
            sz += n/p;
            n /= p;
        }
        return sz;
    }
};

拓展

计算 n ! n! n! p p p 因子的个数根据上述推导的过程同样成立。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值