C++二分查找算法:阶乘函数后 K 个零

简介: C++二分查找算法:阶乘函数后 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 的条件。

示例 3:

输入: k = 3

输出: 5

参数范围

0 <= k <= 109

分析

时间复杂度

O(logn*log5n)。FirstEqualMore内的循环logn次,GetNum内循环log5N。

0个数

0的个数就是2和5的个数的较小者。5的个数一定不会多余2的个数,所以计算5的个数就可以了。

如果5x<=value,那么2x一定小于value。

除非是0个,否则5的个数一定不会等于2的个数。

令x>0,则5x/2 = 2x+x/2 >2x > x

5个数

初步想法

非25的倍数,5的倍数 +1
非125的倍数,25的倍数 +2
非625的倍数,125的倍数 +3

可以这样想

5的倍数 +1
25的倍数 +1
125的倍数 +1

二分

初:寻找第一个和最后一个x,使得f(x)等于k,两者相减再+1。要特殊处理不存在f(x)等于k。所以改成寻找x1=第一个f(x)大于等于k,x2=第一个f(x)大于k,x2也是第一个f(x)大于等于k+1。

代码

核心代码

class Solution {
public:
int preimageSizeFZF(int k) {
return FirstEqualMore(k + 1) - FirstEqualMore(k);
}
int FirstEqualMore(int k)
{
long long left = -1, right = k * 5LL;
while (right - left > 1)
{
const auto mid = left + (right - left) / 2;
if (GetNum(mid) >= k)
{
right = mid;
}
else
{
left = mid;
}
}
return right;
}
long long GetNum(long long llVaue)
{
long long llRet = 0;
long long five = 5;
while (five <= llVaue)
{
llRet += llVaue / five;
five *= 5;
}
return llRet;
}
};

测试用例

template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}
template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}
int main()
{
vector<vector> grid;
int res = 0;
{
Solution slu;
res = slu.preimageSizeFZF(0);
Assert(5, res);
}
{
Solution slu;
res = slu.preimageSizeFZF(5);
Assert(0, res);
}
{
Solution slu;
res = slu.preimageSizeFZF(3);
Assert(5, res);
}
//CConsole::Out(res);

}

2023年3月旧代码

如果f(x)等于k,则f(x+1)、f(x+2)、f(x+3)、f(x+4)都等于k。如果不存在f(x)等于k,则结果为0。所以只有两种返回值,5或0。

class Solution {
public:
int preimageSizeFZF(int k) {
int left = 0, right = 1000 * 1000 * 1000 + 1;
while (right > left + 1)
{
int iMid = left + (right - left) / 2;
const int iNum = GetFiveNum(iMid);
if (iNum == k)
{
return 5;
}
else if (iNum < k)
{
left = iMid;
}
else
{
right = iMid;
}
}
return (GetFiveNum(left) == k) ? 5 : 0;
}
//获取[0,iMax*5] 质因数5的个数
int GetFiveNum(int iMax)
{
int iNum = iMax;
int tmp = 5;
while (iMax >= tmp)
{
iNum += iMax / tmp;
tmp *= 5;
}
return iNum;
}
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

洒家想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
墨家名称的来源:有所得以墨记之。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17


相关文章
|
8天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
6天前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
14天前
|
算法 索引
【算法】——二分查找合集
二分查找基础模版和进阶模版,查找元素位置,搜索插入位置,x的平方根,山脉数组的峰顶索引,寻找峰值,点名
|
13天前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
35 4
|
3月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
3月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
110 6
|
3月前
|
算法 C# 索引
C#二分查找算法
C#二分查找算法
|
3月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
51 0
|
3月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
41 3
|
3月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
508 1