Algorithm --> 求阶乘末尾0的个数
2015-10-24 16:27
399 查看
[b]求阶乘末尾0的个数[/b]
(1)给定一个整数N,那么N的阶乘N!末尾有多少个0?比如:N=10,N!=3628800,N!的末尾有2个0。
(2)求N!的二进制表示中最低位为1的位置。
[b]第一题[/b]
考虑哪些数相乘能得到10,N!= K * 10M其中K不能被10整除,则N!末尾有M个0。
对N!进行质因数分解: N!=2X*3Y*5Z…,因为10=2*5,所以M与2和5的个数即X、Z有关。每一对2和5都可以得到10,故M=min(X,Z)。因为能被2整除的数出现的频率要比能被5整除的数出现的频率高,所以M=Z。
解法1:问题转化为求N!因式分解中5的指数。
改进不要从1开始循环的,只有5的倍数才能够被5整除
解法2:Z =[N/5] + [N/52] + [N/53] + …
[N/5] 表示不大于N的的数中5的倍数贡献一个5, [N/52] 表示不大于N的数中52的倍数在贡献一个5……
或者
[b]第二题[/b]
把一个二进制除以2的过程如下:
判断最后一个二进制是否为0:若为0将二进制数右移1位,即为商;若为1,则说明这个数是奇数,不能被2整除。
所以判断N!的二进制表示中最低位为1的位置的问题可以转换为求N!中含有质因数2的个数的问题。即位置为N!含有质因数2的个数加1.
解法1:N!中含有质因数2的个数等于:[N/2]+[N/4]+[N/8]+…
解法2:N!中含有质因数2的个数等于N减去N的二进制表示中1的数目。
以下为规律的推导:N!中含有2的质因数的个数等于[N/2]+[N/4]+[N/8]+…
对于11011即:
1101+110+11+1 = (1000+100+1) + (100+10) + (10+1) + 1
= 1000+100+10+1 + 100+10+1 + 1
= 1111+111+1
= 10000-1 + 1000-1 + 10-1 + 1-1
= 11011-(N的二进制表示中含有1的个数)
(1)给定一个整数N,那么N的阶乘N!末尾有多少个0?比如:N=10,N!=3628800,N!的末尾有2个0。
(2)求N!的二进制表示中最低位为1的位置。
[b]第一题[/b]
考虑哪些数相乘能得到10,N!= K * 10M其中K不能被10整除,则N!末尾有M个0。
对N!进行质因数分解: N!=2X*3Y*5Z…,因为10=2*5,所以M与2和5的个数即X、Z有关。每一对2和5都可以得到10,故M=min(X,Z)。因为能被2整除的数出现的频率要比能被5整除的数出现的频率高,所以M=Z。
解法1:问题转化为求N!因式分解中5的指数。
int countZero(int N) { int ret = 0; int j; for(int i=1; i<=N; i++) { j = i; while(0==j%5) { ret++; j /= 5; } } return ret; }
改进不要从1开始循环的,只有5的倍数才能够被5整除
int numOfZero(int n) { int num = 0, i, temp; for(i=5; i<=n; i+=5) { temp = i; while(0 == temp%5) { temp /= 5; num++; } } return num; }
解法2:Z =[N/5] + [N/52] + [N/53] + …
[N/5] 表示不大于N的的数中5的倍数贡献一个5, [N/52] 表示不大于N的数中52的倍数在贡献一个5……
int countZero(int N) { int ret = 0; while(N) { ret += N/5; N /= 5; } return ret; }
或者
int numOfZero(int n) { int num = 0, i; for(i=5; i<=n; i*=5) { num += n/i; } return num; }
[b]第二题[/b]
把一个二进制除以2的过程如下:
判断最后一个二进制是否为0:若为0将二进制数右移1位,即为商;若为1,则说明这个数是奇数,不能被2整除。
所以判断N!的二进制表示中最低位为1的位置的问题可以转换为求N!中含有质因数2的个数的问题。即位置为N!含有质因数2的个数加1.
解法1:N!中含有质因数2的个数等于:[N/2]+[N/4]+[N/8]+…
int lowestOne(int N) { int ret = 1; while(N) { N >>= 1; ret += N; } return ret; }
解法2:N!中含有质因数2的个数等于N减去N的二进制表示中1的数目。
以下为规律的推导:N!中含有2的质因数的个数等于[N/2]+[N/4]+[N/8]+…
对于11011即:
1101+110+11+1 = (1000+100+1) + (100+10) + (10+1) + 1
= 1000+100+10+1 + 100+10+1 + 1
= 1111+111+1
= 10000-1 + 1000-1 + 10-1 + 1-1
= 11011-(N的二进制表示中含有1的个数)
相关文章推荐
- GO-SRS with TravisCI
- HDU 4982 Goffi and Squary Partition(BestCoder Round #6)
- Run Django on Tornado
- Go语言学习:Channel是什么?
- .NET平台BigO算法复杂度备忘
- 批量替换和转移目录的东东
- Java、Scala和Go语言多线程并发对比测试结果和结论
- GoAhead 嵌入式web
- scheduling algorithm
- Mac OS上设置Django开发环境
- 跟着猫哥学Golang[1] - Hello World!
- hdu1850 Being a good boy(尼姆博弈)
- Why The Golden Age Of Machine Learning is Just Beginning
- Scrambled Polygon - POJ 2007(求凸包)
- Go写的计费回调Server
- hdoj3966Aragorn's Story【树链刨分】
- EGOCache缓存框架详细讲解,egocache缓存框架
- 安卓系统学习--获取Google安卓系统源码
- 基于 Golang 的 xls 读取类库:xls
- GO项目目录