172.阶乘后的零 | 793.阶乘函数后k个零

本文解析了计算阶乘中尾随零数量的方法,通过分解因子5的个数,并应用二分查找解决f(x)等于k的非负整数x数量问题。讨论了如何利用Solution类实现解决方案,包括countZero函数和preimageSizeFZF函数的应用。

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

172.阶乘后的零

给定一个整数 n ,返回 n! 结果中尾随零的数量。

提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1

示例 1:

输入:n = 3
输出:0
解释:3! = 6 ,不含尾随 0
示例 2:

输入:n = 5
输出:1
解释:5! = 120 ,有一个尾随 0

 思路:

n!中尾随0的数量 = n!可以分解出因子5的个数

因为有因子2和因子5,2X5=10,就可以提供一个0,而n!中只要是偶数就至少可以提供一个因子2,即因子2比因子5多的多,所以n!中的因子5的个数就等于n!中尾随0的个数(拿到一个因子5就可以和因子2凑出一个尾随0)。

class Solution {
public:
    //n!的结果中尾随0的数量 = n!可以分解出因子5的个数
    //例子:125!=125*124*123*...*2*1
    /*
    125/5=25,5的倍数肯定可以提供一个因子5,如:5,10,15,20,25...
    125/25=5,25的倍数肯定可以提供两个因子5,如:25,50,75,100,125
    125/125=1,125的倍数肯定可以提供三个因子5,如:125
    所以125!共可以提供25+5+1=31个因子5,也就有31个尾随0。
    */
    int trailingZeroes(int n) {
        int res=0;
        int dis=5;
        while(dis<=n)
        {
            res+=n/dis;
            dis*=5;
        }
        return res;    
    }
};

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,找出返回能满足 f(x) = k 的非负整数 x 的数量。

示例 1:

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

输入:k = 5
输出:0
解释:没有匹配到这样的 x!,符合 k = 5 的条件。

思路:二分搜索

要求有多少个数满足阶乘后的0的个数等于k,就是在求满足条件的数中,最小的数是多少,最大的数是多少,最大值最小值一减,差就是结果。

因为在穷举 n = 1 ~ LONG_MAX 的过程中,随着 n 的增加,n! 肯定是递增的,阶乘后的0的个数肯定也是递增的,所以可以利用二分查找,找到符合条件的数的最小值(搜索左侧边界),找到符合条件的数的最大值(搜索右侧边界)。

class Solution {
public:
    long countZero(long n)//返回n!后的0的个数
    {
        long res=0;
        long dis=5;
        while(dis<=n)
        {
            res+=n/dis;
            dis*=5;
        }
        return res;
    }

    int preimageSizeFZF(int k) 
    {
       return rightBound(k)-leftBound(k)+1;
    }

    long rightBound(int k)//搜索右侧边界
    {
        long low=0;
        long high=LONG_MAX;
        while(low<high)//左闭右开区间
        {
            long mid=low+(high-low)/2;
            if(countZero(mid)>k)
            {
                high=mid;
            }
            else if(countZero(mid)<k)
            {
                low=mid+1;
            }
            else//找到了符合条件的数,但是不返回,依然向右逼近
            {
                low=mid+1;
            }
        }
        return low-1;
    }

    long leftBound(int k)//搜索左侧边界
    {
        long low=0;
        long high=LONG_MAX;
        while(low<high)//左闭右开区间
        {
            long mid=low+(high-low)/2;
            if(countZero(mid)<k)
            {
                low=mid+1;
            }
            else if(countZero(mid)>k)
            {
                high=mid;
            }
            else//找到符合条件的数,但是不返回,依然向左逼近
            {
                high=mid;
            }
        }
        return low;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值