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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/166495.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES6学习

let和const命名 let基本用法-块级作用域 在es6中可以使用let声明变量&#xff0c;用法类似于var ⚠️ let声明的变量&#xff0c;只在let命令所在的代码块内有效 {let a 10;var b 20; } console.log(a); //a is not defined console.log(b); //20不存在变量提升 var命令…

Stable Diffusion webui 源码调试(一)

Stable Diffusion webui 源码调试&#xff08;一&#xff09; 个人模型主页&#xff1a;LibLibai stable-diffusion-webui 版本&#xff1a;v1.4.1 内容更新随机&#xff0c;看心情调试代码~ 调试txt2img的参数和工作流 文件 /work/stable-diffusion-webui/modules/txt2img…

如何在Visual Studio上创建项目并运行【超级详细】

工欲善其事&#xff0c;必先利其器。想要学好编程&#xff0c;首先要把手中的工具利用好&#xff0c;今天小编教一下大家如何在史上最强大的编译器--Visual Studio上创建项目。&#x1f357; 一.打开编译器&#x1f357; 双击你电脑上的vs&#xff0c;(2012,2019,2022)都行。&…

【vite】vite.defineConfig is not a function/npm无法安装第三方包问题

当使用vite命令 npm init vite-app 项目名称时配置 import vue from vitejs/plugin-vueexport default defineConfig({plugins: [vue()] })会报错vite.defineConfig is not a function 还有就是npm下载的时候也会报错 原因vite插件vitejs/plugin-vue和vite版本问题 解决 调…

数据结构-栈和队列力扣题

目录 有效的括号 用队列实现栈 用栈实现队列 设计循环队列 有效的括号 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 这道题可以用栈来解决&#xff0c;先让字符串中的左括号 ( &#xff0c; [ &#xff0c; { 入栈&#xff0c;s指向字符串下…

潼南柠檬产业发展大会举行 这三个场景“柠”聚了人气

华龙网讯&#xff08;首席记者 羊华&#xff09;今&#xff08;6&#xff09;日下午&#xff0c;2023中国潼南柠檬产业发展大会正式举行。潼南区准备了“大礼包”&#xff0c;既有专业论坛峰会&#xff0c;也首发了“柠檬产业大脑”&#xff0c;还进行了招商引资集中签约&#…

nacos做服务配置和服务器发现

一、创建项目 1、创建一个spring-boot的项目 2、创建三个模块file、system、gateway模块 3、file和system分别配置启动信息,并且创建一个简单的控制器 server.port9000 spring.application.namefile server.servlet.context-path/file4、在根目录下引入依赖 <properties&g…

让深度神经网络绘画以了解它们是如何工作的

一、说明 深度学习如此有效&#xff0c;这真是一个谜。尽管有一些关于深度神经网络为何如此有效的线索&#xff0c;但事实是没有人完全确定&#xff0c;并且深度学习的理论理解是一个非常活跃的研究领域。 在本教程中&#xff0c;我们将以一种不寻常的方式触及问题的一个小方面…

计算机基础知识49

三板斧的使用(views.py) 三个方法&#xff1a;HttpResponse: 返回的是字符串render : 返回html文件redirect : 返回加载HTML页面的 def html(request):print(from html)# return HttpResponse(request) # 它返回的是字符串return render(request,html.html) # 返回html# ret…

【c++】——类和对象(中)——赋值运算符重载

作者:chlorine 专栏:c专栏 你站在原地不动,就永远都是观众。 【学习目标】 拷贝复制——赋值运算符重载 目录 &#x1f393;运算符重载的初步认识 &#x1f308;运算符重载 &#x1f308;赋值运算符重载格式 (上) &#x1f308;operator__判断俩个日期是否相等 &#x…

Mysql 一步到位实现插入或替换数据(REPLACE INTO语句)

单条数据插入/替换 比如有一个数据表叫test_table&#xff0c;包含: 主键&#xff1a;key_id数据&#xff1a;value 运行&#xff1a; REPLACE INTO test_table (key_id,value) VALUES ("id_1","value_1"); REPLACE INTO test_table (key_id,value) VAL…

使用 Socks5 来劫持 HTTPS(TCP-TLS) 之旅

MITM 劫持的过程中&#xff0c;HTTP 协议并不是唯一选择。 实际在 MITM 使用过程中&#xff0c;BurpSuite 和 Yakit 提供的交互式劫持工具只能劫持 HTTP 代理的 TLS 流量&#xff1b;但是这样是不够的&#xff0c;有时候我们并不能确保 HTTP 代理一定生效&#xff0c;或者说特…