现在的位置: 首页 > 综合 > 正文

质数分解——解决一个有关阶乘问题

2014年05月18日 ⁄ 综合 ⁄ 共 1248字 ⁄ 字号 评论关闭

题目:给定一个整数N,请问N!这个数末尾有多少个0?

解决方案1:计算N!,并搜索其末尾,判断0的个数。N!可能过大,数会溢出,如果用该办法,需自己完成一个大数乘法的类,才会好用!

解决方案2:对N!进行质因数分解,可知N!=pow(2,x)*pow(3,y)*pow(5,z)...,能让末尾有零的必然是2*5。可以想见,2的个数远多于5的个数,即 x>z ,所以,末尾应该有z个0。

解决方案2的代码1:

public static int calZero(int a){
		int ret=0;
		for(int i=1;i<=a;++i){
			if(i%5==0){
				int j=i;
				while(j%5==0){
					ret++;
					j=j/5;
				}
			}
		}
		return ret;
	}

对代码1的分析:

事实上,while语句中就具备了if语句判断的功能,多写一个if语句是毫无意义。所以应修改为:

代码2:

	public static int calZero(int a){
		int ret=0;
		for(int i=1;i<=a;++i){
			int j=i;
			while(j%5==0){
				ret++;
				j=j/5;
			}
		}
		return ret;
	}

对于这个问题,网上有更简短的代码:

代码3:

	public static int calZero(int a){
		int ret=0;
		while(a>0){
			ret+=a/5;
			a/=5;
		}
		return ret;
	}

对于代码3的分析:

从思想的角度来看,代码2和代码3都是同样的思考方式,即计算N!中质因数的个数。在代码3中,计算方法是 Z=[N/5]+[N/25]+[N/125]+... ,可理解为,[N/5]不大于N的数中,5的倍数贡献一个5,[N/25]表示不大于N的数中25的倍数再次贡献一个5,以此类推。如N=25时,5的倍数有5,10,15,20,25,其中5、10、15、20均贡献1个5,25贡献2个5,因为25=5*5!

============================================================

题目:给定整数N,求N!的二进制标识中最低位1的位置

解决方法1:依旧是求出N! 然后转换二进制,并最终得结果。缺点:复杂,需考虑数的溢出问题。

解决方法2:判断一个二进制数的最低位1的位置,可如下判断:检查当前是否为1,不是则将该二进制数右移一位。循环直至当前末位为1。所以,欲求N! 二进制表示中最低位1的位置,即可将N!的二进制表示右移,直至末位为1。由于右移在算术中是除2的意思,所以该问题的实质就是求N!中含质因数2的个数!最后的答案为N!中含质因数2的个数加1。

代码:

	public static int loc(int N){
		int ret=0;
		while(N!=0){
			N>>=1;
			ret+=N;
		}
		return ret+1;
	}

代码分析:

代码思想是计算N!中质因数为2的个数,即为 [N/2]+[N/4]+[N/8]+[N/16]+... 。

总结:

质因数的分解是解决有关数字的算法问题的一个思考方向,其中的思想还蛮巧妙。

抱歉!评论已关闭.