《编程之美》读书笔记(三)——阶乘结果末尾"0"的个数

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
对于第一个问题,我起初的思路如下:
     能贡献末尾“0”的数有两类,一类是自身以“0”结尾,例如,10,560,1000等,另一类是个位数是2和5相乘得到。因为是阶乘,从1到N,所以对于每个个位为5的数,总能找到一个其他位相同个位为2的数与之匹配。所以,只需要去数[1,N]中以“0”结尾的数总共多少个“0”,再加上N/10+(N%10<5?0:1)【个位数为5的数的个数】。
     从1到N,出现“0”结尾次数为N/10;出现"00"结尾次数为N/100【个位上的“0”已经被记录,此处不记】;...,因此,第一类数含"0"总数为(N/10+N/100+N/1000+...)

     这种思路是错误的!!错的原因在于个位为5的数可能可以产生多余1个“0”,譬如25*4=100,而上述思路只计1个“0”,因此结果偏小。
     
看来还是书上给的思路比较好。

问题转化(简化):
书上最开始是对问题进行转化,首先,分析结尾的“0”是由因子2和5相乘得到,进而考虑对N!进行因式分解,考察其中因子2和5的个数,结尾“0”的个数等于Min(#(2),#(5)),直观地可知道#(5)<#(2),因而问题可以转化求N!中因子5的个数#(5)。这种思路的好处是问题形式统一化了,而不是像我原本思路那样分情况讨论。

求#(5),
     第一种思路就很直接,求1到N各个数中含有因子5个数求和。
     第二种思路书中直接给了个式子,不直观。我的理解就跟上面最开始思路挺像的。从1到N,能被5整除的数的个数为N/5;能被25的数的个数为N/25【被5整除的情况已经被计算,此处只算一次】;...,因此,因子5的总数为(N/5+N/25+N/125+...)。

第二个问题,问二进制形式末尾“0”的个数。
还是问题转化,N!右移一位就减少一个“0”,也相当于除以2。因此,末尾“0”的个数等于N!中因子2的个数。解决方法与题1类似,N/2+N/4+N/8+...。但是书中给了一个更巧妙的捷径,N!中含有质因子2的个数等于N减去N的二进制表示中“1”的个数。书中只给了例子,没有证明。

下面尝试证明,思路是证明 N/2+N/4+N/8+...+二进制中“1”的个数 = N成立:
先给个例子,N = 1010
则 N/2 = 101, N/4 = N/2 /2 = 10(余数1), N/8 = N/4 /2 = 1,N/16 = N/8 /2 = 0(余数1
直观的知道余数1对应着N的二进制表示中的“1”,
因此,做加法的时候从N/16开始: 
N/16+N/16+余数1 = N/8
N/8+N/8 = N/4
N/4+N/4+余数1 = N/2
N/2+N/2 = N
因此,N/2+N/4+N/8+...+二进制中“1”的个数 = N 得证。对于不同的N同样成立。

相关题目那里问的"方幂",原来就是整数幂的意思。
也就是说是100000之类,只有一个“1”,给的提示也是之前《求二进制数中“1”的个数》第三种方法,n>0 && n&(n-1) == 0



编程》——读书笔记 最近花了几天时间把《编程》这本书好好读了一遍,感觉收获还是挺大的。 于是决定做个笔记,算是简单的摘录一些书中的精彩思想,也算重新回顾思考下   1.5 快速找出机器故障 问题描述: 有很多的ID(可能位数很大),其中只有一个ID出现的次数小于2,其他正常ID出现的次数都等于2,求这个次数为1的ID 精彩解法: 将所有的数从头到尾异或一遍,这样得出来的最终结果就是所求的答案。 拓 阅读详情

相关推荐

编程学习笔记——数字相关(一)

1.二进制数中1个数 ①有一个字节(8bit)变量,求其二进制表示"1"个数。 思路一:二进制数的最低位如果为1,那么它不可以被2整除,反之可以。我们可以先判断最后一位是否为1,然后右移一位,重复判断最后一位是否为1,直至该数为0;这个算法时间复杂度为O(N),其中N是这个二进制数的位数; 思路二:对于一个二进制数X,运算X&(X-1)可以将最后二进制表示中的最后一位1置为0,重复该操

ivokky的专栏 1001

c语言 n阶阶乘0个数,计算n的阶乘(n!)末尾0个数

题目:给定一个正整数n,请计算n的阶乘n!末尾所含有“0”的个数。举例:5!=120,其末尾所含有的“0”的个数110!= 3628800,其末尾所含有的“0”的个数为2;20!= 2432902008176640000,其末尾所含有的“0”的个数为4解题思路:两个大数字相乘,都可以拆分成多个质数相乘,而质数相乘结果尾数为0的,只可能是2*5。如果想到了这一点,那么就可以进一步想到:两个数相乘...

weixin_29568911的博客 2750

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

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

bertzhang的专栏 4564

第十二周项目二

/* *Copyright (c) 2014, 烟台大学计算机学院 *All rights reserved. *文件名称:test.cpp *作者:于凯 *完成日期:2014年 1118日 *版本号:v1.0 * *问题描述: */ #include using namespace std; int main() {

yukai98524的专栏 281

【C语言】——100阶乘0个数

编程实现函数,求出100阶乘的最后连续0个数。 如:20!中有4个0 #include <stdio.h> #include<stdlib.h> int main() { int a=0; for (int i = 1; i<=100; i++) { if (i % 5==0) { a++; if (i % 25 == 0) { a++; } } } printf("100阶乘0个数:%d\.

weixin_44002476的博客 435

[读书笔记]编程(二)

[读书笔记]编程(二)2.1二进制数中1个数 问题:对于一个字节(8bit)的无符号整形变量,求其二进制表示中“1”的个数,要求算法的执行效率尽可能高。 思路: n = n & (n-1);当然因为只有8bit所以直接定义一个256的int数组表,直接返回结果,时间复杂度是O(1)。2.2不要被阶乘吓到 问题:1.给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=362

xy_cpp的博客 567

编程读书笔记阶乘

题目:         看到题目,很容易冒出一种想法:计算出N!的结果,并对结果除以10取余。直到余数不为0为止。 int Factorial(int n) { int a = 0, sum = n; while(--n) { sum *= n; } while(sum % 10 == 0) { sum /= 10; a ++; } return a; }

一介渔夫 2940

编程读书笔记2.2—不要被阶乘吓倒

问题 1) 给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3 628 800,N!的末尾有两个0。     2) 求N!的二进制表示中最低位1的位置。  3)给定整数n,判断它是否为2的方幂       问题1详解              解法1:                       解法2:                    代

yuhan_9204的专栏 389

编程读书笔记:给定一个整数N,求N!末尾有多少个0

问题:给定一个整数N,求N!末尾有多少个0          这个题目不能直接求出N!的值,这样可能会溢出。首先考虑N!=K*10^M,并且K不能被10整除,那么N!末尾有M个0。再考虑对N!进行质因数分解,N!=(2^X)*(3^Y)*(5^Z)...,由于10=2*5,所以M只和X和Z有关,每一对2和5相乘都可以得到一个10,于是M=min(X,Z);不能看出X>=Z.所以把公式简化为M=Z

xiaoding133的专栏【Stay hungry,Stay foolish】 4223

编程读书笔记之---”不要被阶乘吓到“

问题一:给定一个整数N,那么N的阶乘末尾有多少个0呢?例如N = 10, N! = 362800,N! 的末尾有两个0. 问题二:求N! 的二进制表示中,最低位1的位置。 问题一的解法一: 最简单的方法就是把N! 算出来,就可以知道末尾有多少个0了。 问题一的解法二: 我们这样想,末尾0可以从哪里得到呢,10的倍数,例如像10,20,100....这样的,可以贡献0,还有就是2 ...

weixin_30782293的博客 99

编程读书笔记_杂项

编程 读书笔记 1.1 让CPU占用率听你指挥P7页的那个汇编代码(16位)有点过时。另外,对32位汇编,空循环,常用到的寄存器是eax或ecx。  1.5 快速找出机器故障看了好几遍,还是看不懂题目,尽管猜到了要考什么。问题一问的有点莫名其妙,没说明为什么有个ID会只出现一次,只出现一次的ID是否只有一个;问题二的两个小问题本意都是要求找丢失的ID,但却把这个要求

flyinghearts的专栏 1245

编程读书笔记-第二章

#include #include using namespace std; int Count1(BYTE v) { int num=0; while(v) { num += v & 0x01; v>>=1; } return num; } void main() { BYTE v=11100110; cout<<Count1(v); }

ljp1919的专栏 674

编程--第二章 读书笔记

2.1二进制数中的1个数 最优解法:复杂度为O(k) k为二进制1个数 public int count(int n){ int num=0; while(n){ //从后往前数‘1’的个数 //n&amp;(n-1)这种方式可以消去一个‘1’ //e.g. 10000&amp;01111=00000 n...

ida20111117的博客 187

编程读书笔记之:杂项

 1.1 让CPU占用率听你指挥P7页的那个汇编代码(16位)有点过时。另外,对32位汇编,空循环,常用到的寄存器是eax或ecx。  1.5 快速找出机器故障看了好几遍,还是看不懂题目,尽管猜到了要考什么。问题一问的有点莫名其妙,没说明为什么有个ID会只出现一次,只出现一次的ID是否只有一个;问题二的两个小问题本意都是要求找丢失的ID,但却把这个要求给省略了,按上下文语义,问

BOPGroup的专栏 1001

读书笔记-数论

离散数学之数论 翻了翻课本,看到数论一章有一个问题:20!的二进制表示从最低位数起有多少个连续的 0 。 课本上直接求 1到20的数 含有因子2的个数和,求出来是 18. 各种不理解,然后百度。看到了《编程》一书有同样的问题。 以下内容部分摘自: 大神的读书笔记有两个问题,用到的方法类似 (1)给定一个整数N,那么N的阶乘N!末尾有多少个0?比如:N=10,N!=3628800,N

你记不住我 635

js的读书笔记

一、js中%=的使用方法(取余0) var a = (10 * 3 - 4 / 2 + 1) % 2 , /js中 %= 的使用/ b = 3; b %= a + 3; document.write(a); document.write(""); document.write(b); document.write(""); document.write(a++); /* a++ 或类似的...

qq_36718975的博客 322

《Effective C++》读书笔记之item48:认识template元编程

1.模板元编程可以将部分执行期的任务提前至编译期完成,从而可以更早发现错误,更加高效(编译时间会变长,但是执行期的效率会更高)。 2.模板元编程是图灵完备的,可以执行分支语句和循环(通过递归实现)。如解决阶乘问题的代码: template //一般情况,递推关系式 struct Factorial{ enum{value = n * Factorial::value}; }; temp

banguijun的专栏 1848

【c++ templates读书笔记】【7】模板元编程

模板实例化机制是一种基本的递归语言机制,可以用于在编译期执行复杂的计算。这种随着模板实例化所出现的编译器计算通常被称为template metaprogramming。 例子一,计算阶乘: //Pow.h #ifndef POW_H #define POW_H template class Pow{ public: enum { result = M*Pow::result }; };

ruan875417的专栏 450

python编程自然数表达式_python编程导论读书笔记【3】

### 递归递归的定义包含了两部分:至少有一种基本情形可以直接得到某种特定情形的结果,至少有一种递归情形(或称归纳情形)定义了该问题在其他情形下的结果。世界上最简单的递归定义可能就是自然数的阶乘函数。 1!=1 (n+1)!=(n+1)*n!### 斐波那契数列```pythondef fib(n):"""假定n是正整数,返回第n个斐波那契数"""if n == 0 or n == 1:retur...

weixin_39653733的博客 259
上一篇: 《编程之美》读书笔记(二)——二进制数中“1”的个数
下一篇: 《编程之美》读书笔记——[1~N]出现“1”的次数
210在吾道
博客等级 码龄13年 0粉丝 8原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值