N!的末尾有几个零以及二进制表示最右边1的位置

给定一个整数N,求解整数N!末尾0的个数 问题描述 1、给定一个整数N,阶乘N!末尾有多少个0 2、求N!的二进制表示中最低位1的位置 1、给定一个整数N,阶乘N!末尾有多少个0 举例:10!=3 628 800,则 N!的末尾有两个0 思路:   即,知道 Z ,就知道N!中含有0的个数 方法一:求出1~N中每一个数被5整除的因子的个数,比较笨 代码: [cpp 阅读详情

问题一:求n!后面有多少个0。

        N的阶乘可以分解为: 2的X次方,3的Y次方,4的5次Z方,.....的成绩。由于10 = 2 * 5,所以M只能和X和Z有关,每一对2和5相乘就可以得到一个10,于是M = MIN(X,Z),不难看出X大于Z,因为被2整除的频率比被5整除的频率高的多。所以可以把公式简化为M=Z.
 由上面的分析可以看出,只要计算处Z的值,就可以得到N!末尾0的个数。
令f(x)表示正整数x末尾所含有的“0”的个数,则有:
      当0 < n < 5时,f(n!) = 0;
      当n >= 5时,f(n!) = k + f(k!), 其中 k = n / 5(取整)。

 显然,对于阶乘这个大数,我们不可能将其结果计算出来,再统计其末尾所含有的“0”的个数。所以必须从其数字特征进行分析。下面我们从因式分解的角度切入分析。

    我们先考虑一般的情形。对于任意一个正整数,若对其进行因式分解,那么其末尾的“0”必可以分解为2*5。在这里,每一个“0”必然和一个因子“5”相对应。但请注意,一个数的因式分解中因子“5”不一定对应着一个“0”,因为还需要一个因子“2”,才能实现其一一对应。

    我们再回到原先的问题。这里先给出一个结论:
    结论1: 对于n的阶乘n!,其因式分解中,如果存在一个因子“5”,那么它必然对应着n!末尾的一个“0”。
    下面对这个结论进行证明:
    (1)当n < 5时, 结论显然成立。
    (2)当n >= 5时,令n!= [5k * 5(k-1) * ... * 10 * 5] * a,其中 n = 5k + r (0 <= r <= 4),a是一个不含因子“5”的整数。
    对于序列5k, 5(k-1), ..., 10, 5中每一个数5i(1 <= i <= k),都含有因子“5”,并且在区间(5(i-1),5i)(1 <= i <= k)内存在偶数,也就是说,a中存在一个因子“2”与5i相对应。即,这里的k个因子“5”与n!末尾的k个“0”一一对应。
    我们进一步把n!表示为:n!= 5^k * k! * a(公式1),其中5^k表示5的k次方。很容易利用(1)和迭代法,得出结论1。
    
    上面证明了n的阶乘n!末尾的“0”与n!的因式分解中的因子“5”是一一对应的。也就是说,计算n的阶乘n!末尾的“0”的个数,可以转换为计算其因式分解中“5”的个数。

    令f(x)表示正整数x末尾所含有的“0”的个数, g(x)表示正整数x的因式分解中因子“5”的个数,则利用上面的的结论1和公式1有:
       f(n!) = g(n!) = g(5^k * k! * a) = k + g(k!) = k + f(k!)
所以,最终的计算公式为:
    当0 < n < 5时,f(n!) = 0;
    当n >= 5时,f(n!) = k + f(k!), 其中 k = n / 5(取整)。

代码如下:

int LowestZeros2(int N)
{
	int ret = 0;
	while (N)
	{
		ret += N /5;
		N /= 5;
	}
	return ret;
}
原始的求5的指数代码:

int LowestZeros(int N)
{
	int ret = 0;
	for(int i = 1;i <= N; i++)
	{
		int j = i;
		while(j % 5 == 0)
		{
			ret++;
			j /= 5;
		}
	}
	return ret;
}
问题二:求N!的二进制表示中最低位1的位置。

同上即为求N!中质因数2的个数,利用与上相同的思路,可以得到如下代码:

int LowestOne(int N)
{
	int  ret = 0;
	while(N)
	{
		N >>= 1;
		ret += N; 
	} 
	return ret;
}
测试:

int main()
{
	printf("%d\n",factorial(9));
	printf("%d\n",LowestZeros(25));
	printf("%d\n",LowestZeros2(25));
	printf("%d\n",LowestOne(25));
	getchar();	
}
结果:

362880
6
6
22
REF:

1,http://blog.youkuaiyun.com/niushuai666/article/details/6695790

2,编程之美







C++返回一个数的二进制最右边的一位的实现算法(附完整源码) C++返回一个数的二进制最右边的一位的实现算法C++返回一个数的二进制最右边的一位的实现算法完整源码(定义,实现,main函数测试) C++返回一个数的二进制最右边的一位的实现算法完整源码(定义,实现,main函数测试) #include <iostream> #include <cmath> int position_of_first_set_bit( int num ) { return log2(num & -num) + 1; } int main() { 阅读详情

相关推荐

ScanNet数据集详解

ScanNet 是一个 RGB-D 视频数据集,在超过 1500 次扫描中包含了 250 万个视图,并标注了 3D 相机位姿、表面重建和实例级的语义分割。为了收集这些数据,设计了一个易于使用且具有扩展性的 RGB-D 捕获系统,包括自动化的表面重建和众包的语义标注。如果您想下载 ScanNet 数据,请使用您的机构邮箱地址填写一份 ScanNet 使用条款协议,并发送至 scannet@googlegroups.com。压缩包是将3D的标注信息“拍扁”成2D图片的结果,对应原始视频的每一帧。

frostmelody 全网同名,大家多多关注呀~ 持续分享优质内容! 3919

算法 | 如何把一个int型二进制数的最右侧的1提取出来?

本文主要介绍如何把一个int型二进制数的最右侧的1提取出来,也就是只保留该int型数对应的二进制最右侧的1,其他的都变为0,并返回对应的10进制数字。现有个数,这个num对应的二进制为,要求把这个数的二进制最右侧的1保留,其他的位置全部变为0,也就是变为,变更后的二进制数对应的十进制为4。从上面两个方案来看,方法二使用位运算比方法一简单的太多了,仅仅简单的一行代码就把功能给实现了,而且在效率方面也远比方法一高的多。

BASK2311的博客 904

FPGA实战:用Verilog实现Costas环载波同步(附Vivado2019.2仿真步骤)

本文详细介绍了如何在FPGA上使用Verilog实现Costas环载波同步,包括核心原理、Vivado2019.2工程配置、代码实现及仿真验证。通过正交下变频、相位误差检测和环路滤波等关键模块的设计,帮助开发者掌握数字通信系统中的载波同步技术,并提供了实用的调试和优化技巧。

k0l1m2n3o的博客 134

二进制最右侧1及其应用

把一个整型数,提取最右侧的1 int N=0000 1101 1000 1100 变成ans=0000 0000 0000 0100 ans=N&(~N+1) 应用: 一个数组中两种数出现了奇数次,其余的数都出现偶数次,找到并且打印这两种数(最右侧1的应用!) 假设两种数是a和b,则两种数异或的结果为ab,则数组所有数异或的结果为ab。 因为a!=b也就是a^b!=0,所以a和b某一位不相等。假设第8位不同,所以根据第8位为0和1,将数组中所有的数分为两组。 将数组中第八位为1的数和 第八.

weixin_43604021的博客 534

Ubuntu Server 22.04.5系统安装教程

该教程主要是演示在服务器上安装Ubuntu server 22.04系统的详细步骤,主要包含,安装系统前的准备(镜像的下载,启动盘的制作),安装系统时的语言选择,网络设置,切换镜像源(可根据实际需求来配置,本文使用清华镜像源),手动分区,用户设置,ssh服务安装等。以上就是关于Ubuntu Server 22.04系统安装的详细过程。

逆水行舟,不进则退。 7761

【2022】人工智能☆✨

1. 朴素⻉叶斯⽅法是⼀种 ( ) ⽅法。A.机器学习的分类B.不确定性推理C.知识表示答案:A解析:朴素贝叶斯分类器是基于贝叶斯定理与特征条件独立假设的分类方法。它通过学习训练数据集来预测未知数据的类别标签,因此属于机器学习中的监督学习分类方法。选项B不确定性推理和选项C知识表示虽然与朴素贝叶斯方法有一定的关联,但它们并不是朴素贝叶斯方法的主要应用领域或定义特性。2. 关于启发式搜索描述正确的是 ( )。

super_mochi1 391

计算机中的二进制

计算机中的二进制简介。

小Y的博客 1541

GPU架构(1.1)--介绍 GPU的 VPU(Vision Processing Unit)架构

基于自研的 VPU(Vision Processing Unit)架构,专为高性能图形处理和深度学习设计。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。这种架构不仅适用于高性能图形处理,还广泛应用于深度学习、科学计算和边缘计算等领域。通过了解 VPU 架构的详细设计和工作原理,读者可以更好地利用这些先进的 GPU 技术,开发出高效、可靠的计算系统。

MHD0815的博客 1300

位运算 二进制数

位运算 二进制数按位异或 “^”按位或 “|”左移运算符 “<<”右移运算符 “>>”实际使用 按位异或 “^” 按位异或运算通常用来将某变量中的某些位取反,且保留其他位不变。 例如,如果需要将int型变量n的低8位取反,而其余位不变,则可以执行: n ^= 0xff; 0xff: 1111 1111 按位或 “|” 按位或运算通常用来将某变量中的某些位置1且保留其他位不变。 例如,如果需要将int型变量n的低8位全置成1,而其余位不变,则可以执行: n |= 0xff; 0xff:

weixin_46075832的博客 1519

基于Simulink的光伏+储能家庭能源管理系统仿真

本文通过Simulink建模,分析了家庭光伏+储能系统的优化调度问题。针对光伏发电与用电高峰不匹配导致电费节省有限的问题,构建了包含5kW光伏、10kWh电池和6kW负荷的完整模型,设计了无控、规则控制和24小时经济优化三种策略。仿真结果显示,经济优化策略可使日电费降低32%,光伏自用率从45%提升至89%,尤其在晚高峰时段能显著减少高价购电。文章详细介绍了物理层建模、分时电价实现和控制策略设计方法,并探讨了天气预测、V2H等高级扩展功能,为家庭能源智能管理提供了实用解决方案。

xiaoheshang_123的博客 188

神经进化实践:用遗传算法替代反向传播优化神经网络

神经进化用来定义应用于深度学习的特定优化模式。在本节中,我们通过遗传算法优化简单深度学习网络的权重/参数,替换在误差反向传播训练过程中的所用优化器。

盼小辉丶的博客 3620

阶乘二进制表示末尾1的位置

阶乘二进制表示末尾1的位置 题目描述 给定一个非负整数N,如果用二进制数表达N!的结果,返回最低位的1在哪个位置上,认为最右的位置为位置0。 输入描述: 第一行一个整数N。 输出描述: 输出一个整数表示答案 示例1 输入 1 输出 0 说明 1! = 1,最低位的1在0位置上 示例2 输入 2 输出 1 说明 2 != 2,最低位的1在1位置上 示例3 输入 1000000000 输出 999999987 备注: 1⩽N⩽10181 \leqslant N \leqslant 10^{18}

MIC10086的博客 429

Debezium报错处理系列之第112篇:Cannot replicate because the master purged required binary logs. Replicate the

Debezium报错处理系列之第112篇:Cannot replicate because the master purged required binary logs.

zhengzaifeidelushang的博客 726

ACM_数论_阶乘N!的末尾有几个零

首先阶乘的一个常识要知道就是25!的末尾6位全是0; 前言: 《编程之美》这本书,爱不释手!  问题描述: 给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=362800,N!的末尾有两个0;求N!的二进制表示中最低位1的位置。   问题1的求解: 分析: 解法一:        首先,最直接的算法当然是直接求出来N!然后看末尾有几个0就行了。但这里存在两个问题:

技术札记 2063

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

n!阶乘末尾有多少个零0

题目: 初阶:1*2*3*……*100 求结果末尾有多少个零。 进阶: N的阶乘末尾有多少个0分析: 一般类似的题目都会蕴含某种规律或简便方法的阶乘末尾一个零表示一个进位,则相当于乘以10而10 是由2*5所得,在1~100当中,可以产生10的有:0 2 4 5 6 8 结尾的数字,显然2是确定的,因为4、6、8当中都含有因子2,所以都可看当是2,那么关键在于5的数量了那么该问题的实质是要求出

TommyZht的专栏 1万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

1*2*3*……*100 求结果末尾有多少个零 网上的答案到底对不对

题目:1*2*3*……*100 求结果末尾有多少个零   分析:一般类似的题目都会蕴含某种规律或简便方法的,阶乘末尾一个零表示一个进位,则相当于乘以10而10 是由2*5所得,在1~100当中,可以产生10的有:0 2 4 5 6 8 结尾的数字,显然2是足够的,因为4、6、8当中都含有因子2,所以都可看当是2,那么关键在于5的数量了那么该问题的实质是要求出1~100含有多

whx5572371的博客 6869

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

求N!阶乘中结尾0的个数,或结果的二进制表示中最后一个1所在的位置

问题1:阶乘结尾0的个数 要想阶乘的结尾是0,那么这个0已经通过5的倍数乘以另一个数获得,例如:5,10,15,20,25...,同时可以注意到这样一个规律,5,10,15,20,30,35,40与某个数相乘后可以贡献1个0,而25,50,75,100...与某个数相乘可以贡献2个0,5^3, 2* 5^3, 3*5^3与某个数相乘时贡献了3个0,依次类推。同时我们注意到,在统计5,10,15,

bertzhang的专栏 4569

N的阶乘中(N!)末尾0的个数

问题1:N!中末尾0的个数?。。 思路1:N!=K x 10^M,且K不能被10整除,那么N!末尾有M个0. 思路2: 进行因数分解,N!=(2^x)x(3^y)x(5^z)..., 由于10=2x5,所以0的个数M只跟x和z有关,且M=min(x,z), 因为能被2整除的数出现的频率比能被5整除的数高得多,所以x>z,所以M=z。 解法1: #include int main() {

jxfang的专栏 1312

如何确定一个N!末尾有多少个零

题目:1*2*3*……*100 求结果末尾有多少个零   分析:一般类似的题目都会蕴含某种规律或简便方法的,阶乘末尾一个零表示一个进位,则相当于乘以10而10 是由2*5所得,在1~100当中,可以产生10的有:0 2 4 5 6 8 结尾的数字,显然2是足够的,因为4、6、8当中都含有因子2,所以都可看当是2,那么关键在于5的数量了那么该问题的实质是要求出1~100含有多

小试牛刀 5352

1024! 末尾有多少个0?

先把答案贴出来,具体证明在下面…… 末尾0的个数取决于乘法中因子2和5的个数。显然乘法中因子2的个数大于5的个数,所以我们只需统计因子5的个数。 是5的倍数的数有: 1024 / 5 = 204个 是25的倍数的数有:1024 / 25 = 40个 是125的倍数的数有:1024 / 125 = 8个 是625的倍数的数有:1024 / 625 = 1个 所以1024!

彦祖老师 4770

编程之美2——N!的二进制表示中最低位1的位置

任何数在计算机内部都是用二进制表示的,可以用这个特性来快速判断N!的二进制表示中最低位1的位置。 解法一: 将一个数的二进制数除以2,若二进制数的末尾是0,则能整除,否则不能整除。 因此,求 N!的二进制表示中最低位1的位置 即为求 N!中有多少个质因数2 以下为代码1: #include using namespace st

my_adu的专栏 1951

求N的阶乘N!末尾有多少个零

求N的阶乘N!末尾有多少个零 解法1: int foo(int n) { int count = 0; for(int i=1; i<=n; ++i) { int t=i; while(t%5==0) { ++count; t/=5; } } } 解法2: int foo(int n) { int count = 0; whi

kevinaxy的专栏 597

笔试算法题(33):烙饼排序问题 & N!阶乘十进制末尾0的个数二进制最低1的位置...

出题:不同大小烙饼的排序问题:对于N块大小不一的烙饼,上下累在一起,由于一只手托着所有的饼,所以仅有一只手可以翻转饼(假设手足够大可以翻转任意块数的 饼),规定所有的大饼都出现在小饼的下面则说明已经排序,则最少需要翻转几次,才能达到大小有序的结果(改变饼的顺序只能整体翻转,不能相邻交换); 分析: 假设饼大小编号为1,……,N,1就是最小的饼,N就是最大的饼,最大的N饼翻转到最下面之前,一...

weixin_34005042的博客 560

给定一个整数N,那么N的阶乘N!末尾有多少个0呢?求N!的二进制表示中最低位1的位置。

题目1:给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3 628 800,N!的末尾有两个0。 初看这样的题目可能会想到直接求出N!的阶乘,然后再计算出0的个数。 显然用这种方法如果N很大的情况下,非常容易溢出。所以我们可以换个角度来分析这个问题。N=1×2×3×4×5×6×··· ×N我们可以对N!进行分解质因数 即N!=2x ×3y ×5z ·····

Number_0_0的博客 1177

n!的末尾0的个数

题目描述: 输入一个正整数n,求n!(即阶乘)末尾有多少个0? 比如: n = 10; n! = 3628800,所以答案为2 。 解题思路: 对于这样的问题,我们可以换个思维方式,它要求0的个数,那么0是怎么来的? 是不是一对2*5得到的0,所以我们可以分解这个问题分,把他看作是求整数n分解质因数后,一共有多少组min(2,5),在当然2的个数肯定比5多,所以我们继续往...

Demons的博客 4136

程序员面试100题之八 不要被阶乘吓倒(二进制表示中最低位1的位置 )

程序员面试100题之八 不要被阶乘吓倒(二进制表示中最低位1的位置 )

fguihbfg的博客 210
上一篇: 二进制数中1的个数
下一篇: 斐波那契(Fibonacci)数列的求法
Scandinavians
博客等级 码龄19年 36粉丝 121原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值