[编程之美] PSet2.2 不要被阶乘吓倒
2014-07-28 14:17
232 查看
问题1:给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3 628 800,N!的末尾有两个0。
问题2:求N!的二进制表示中最低位1的位置。
问题一思路:
解法一:给定一个整数N,那么N的阶乘N!末尾有多少个0的问题可以转换为N!乘式中可以分解出多少个5的问题.因为5和其前面的任何一个偶数相乘都会产生0,所以只需求出在由1到N的数中共可以分解出多少个5.例如25!,可以分解出5(1×5)、10(2×5),15(3×5),20(4×5)25(5×5),共可以分解出6个5,所以25!末尾有6个0;
由此可以推知15!最后有3个0…这事实上也用到了2出现的频次总是高于5出现的频次,所以可以不用管2这个质因数。(最早出现5是在5!,此时2出现频次为3,远高于5出现的频次1,随着N的增大,N!中2频次与5频次差距越来越大。)
那么如何得到N!因式分解的5的个数呢?
解法二:考虑区间贡献,1-5之间贡献了一个5;6-10之间贡献了一个5····也就是每隔5贡献一个5因子,每隔5^2贡献一个5^2因子···,因此原问题转化为按照N以5的幂次划分区间,能够得到多少个区间的问题。
问题二思路:
解法一:问题一解出的是十进制表示的情况,现在由于是二进制表示N!,最低位1表明后面位全部为0。考虑乘以一个2,二进制数左移一位,因此可以考虑2的质因数个数即可求得结果。
解法二:N!中2的质因数个数还等于N-N中二进制表示1的数目,这个规律怎么来的呢?
试看N=11011(二进制表示),那么N!有多少个2质因数呢?由解法一的分析可以得到:
sum=11011>>1 + 11011>>2 + 11011>>3 + 11011>>4 =1101 + 110 + 11 + 1,对该式进行拆分可以得到
sum=(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的个数)
于是解法二代码如下:
相关题目:
给定整数n,判断它是否是n的方幂
if(n>0 && (n&(n-1)==0 )) return true;
问题1:给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3 628 800,N!的末尾有两个0。
问题2:求N!的二进制表示中最低位1的位置。
问题一思路:
解法一:给定一个整数N,那么N的阶乘N!末尾有多少个0的问题可以转换为N!乘式中可以分解出多少个5的问题.因为5和其前面的任何一个偶数相乘都会产生0,所以只需求出在由1到N的数中共可以分解出多少个5.例如25!,可以分解出5(1×5)、10(2×5),15(3×5),20(4×5)25(5×5),共可以分解出6个5,所以25!末尾有6个0;
由此可以推知15!最后有3个0…这事实上也用到了2出现的频次总是高于5出现的频次,所以可以不用管2这个质因数。(最早出现5是在5!,此时2出现频次为3,远高于5出现的频次1,随着N的增大,N!中2频次与5频次差距越来越大。)
那么如何得到N!因式分解的5的个数呢?
//求解阶乘结果中末尾0的个数 //考虑求解从1-N之间的数,能被5整除的次数 int findZeroNum(int N) { int temp = 0; int num = 0; for(int i=1 ; i<=N ; i++){ temp = i; while(temp % 5 == 0){ num++; temp = temp/5; } } return num; }
解法二:考虑区间贡献,1-5之间贡献了一个5;6-10之间贡献了一个5····也就是每隔5贡献一个5因子,每隔5^2贡献一个5^2因子···,因此原问题转化为按照N以5的幂次划分区间,能够得到多少个区间的问题。
//每隔5^i贡献1个5^i因子如0-5 5-10 10-15···都贡献了一个5,而到25的时候贡献了两个5 int findZeroNum(int N) { int num = 0; while(N){ num+=N/5; N = N/5; } }
问题二思路:
解法一:问题一解出的是十进制表示的情况,现在由于是二进制表示N!,最低位1表明后面位全部为0。考虑乘以一个2,二进制数左移一位,因此可以考虑2的质因数个数即可求得结果。
//如果要求N!中2的质因数个数 int findOnePos(int N) { int sum = 0; while(N){ sum += N>>1; N = N>>1; } return sum+1; }
解法二:N!中2的质因数个数还等于N-N中二进制表示1的数目,这个规律怎么来的呢?
试看N=11011(二进制表示),那么N!有多少个2质因数呢?由解法一的分析可以得到:
sum=11011>>1 + 11011>>2 + 11011>>3 + 11011>>4 =1101 + 110 + 11 + 1,对该式进行拆分可以得到
sum=(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的个数)
于是解法二代码如下:
int numOfOne(int i)//i二进制表示中1的个数 { int count = 0; while(i){ i &=(i-1); count++; } return count; } int findOnePos(int N) { return N-numOfOne(N); }
相关题目:
给定整数n,判断它是否是n的方幂
if(n>0 && (n&(n-1)==0 )) return true;
相关文章推荐
- 编程之美-2.2-不要被阶乘吓倒
- 读书笔记之编程之美 – 2.2 不要被阶乘吓倒
- 编程之美-2.2-不要被阶乘吓倒
- 编程之美_2.2_不要被阶乘吓倒
- 编程之美:不要被阶乘吓倒
- 编程之美 2.2 不要被阶乘吓到
- 编程之美--不要被阶乘吓倒
- 编程之美--不要被阶乘吓倒 求N!的质因数2的个数
- 2.2 编程之美--不要被阶乘吓到[zero count of N factorial]
- [编程之美]不要被阶乘吓倒
- 2.2 不要被阶乘吓倒
- 不要被阶乘吓倒(编程之美2.2)
- 【编程之美】2.2不要被阶乘吓到
- 编程之美2.2 不要被阶乘吓倒
- 2.2不要被阶乘吓倒(读书笔记)
- 编程之美2.2——不要被阶乘吓倒
- 编程之美 不要被阶乘吓倒
- 编程之美2.2不要被阶乘吓倒Java版
- 编程之美读书笔记2.2—不要被阶乘吓倒
- 《编程之美》2.2 不要被阶乘吓倒(c++ 源码)