java实现统计N!尾部连续0的个数

这篇博客介绍了如何使用Java实现计算任意正整数N的阶乘(N!)尾部连续0的个数。通过创建ArrayList存储1到N的数,遍历寻找相乘为10的倍数的数并移除,统计相乘得到的0数量。代码中定义了countZero方法,复杂度未提及。

问题描述:

     对任意输入的正整数N,编写java程序求N!的尾部连续0的个数,并指出计算复杂度。如:18!=6402373705728000,尾部连续0的个数是3

(不用考虑数值超出计算机整数界限的问题)


java代码如下:

import java.util.ArrayList;

public class Zero {

	/**
	 * 求n!结果数末尾连续0的个数
	 * 
	 * 思路,从1到n找出依次找出相乘为10的整数倍的数,不重复
	 * 
	 * 
	 * 
	 */
	
	public int countZero(int num){
		ArrayList list=new ArrayList();
		
		int count=0;
		for(int i=1;i<=num;i++){//将num前的所有大于0的正整数全部放入list中
             list.add(i);               			
		}
		
		for(int j=0;j<list.size()-1;j++){//从list第一个正整数开始寻找如果找到了与本数相乘是10的倍数的就将这两个数从list中移除,并进入下一次循环,统计本次相乘后出现的0的个数
		    int k=j+1;
			while(k<list.size()){
				int m=(Integer) list.get(k);
				int n=(Integer)list.get(j);
				int total=m*n;
				if(total%10==0){
					//统计0的个数
					while(total%10==0){
						total=total/10;
						count++;
					}
					
					//移除本次相乘为10的倍数的两个数
					list.remove(k);
					list.remove(j);
					
					break;//跳出while循环,每次只找到开始的数与后面的数相乘为10的倍数的第一个数就行
				}
				
				k++;
				
			}
		}
		
		return count;
	}
	
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Zero zero=new Zero();
		int n=18;
		int count=zero.countZero(n);
		int total=1;
//		for(int i=1;i<=n;i++){
//			total=total*i;
//		}
		System.out.println("统计的0的个数为:"+count);
//		System.out.println("该数的阶乘为:"+total);

	}

}

         在main函数中将变量n设置为你传入的参数就可以统计出该参数阶乘后的末尾0的个数~~~




<think>我们分析问题:计算n的阶乘结果中尾部连续0个数。根据引用[1][2][4]可知,尾部0个数实际上是由因子2和5的个数决定的,而每对2和5就会产生一个0。由于阶乘中因子2的个数通常多于因子5的个数,因此问题转化为计算n的阶乘中因子5的个数。 但是注意:题目要求是从个位数开始向前数连续0个数。注意是连续0,而且是从个位开始。这里有一个关键点,即我们通常计算尾部0个数连续的,直到遇到第一个非数字为止。因此,我们只需要计算因子5的个数(同时因子2足够多)就可以了。 然而,需要注意的是,有些情况可能会产生更多的0?比如当有额外的10(即2*5)时。但实际上,我们通常的方法已经考虑了所有5的因子,包括25(有两个5)、125(有三个5)等。 因此,我们的算法是:计算n的阶乘中因子5的个数。具体方法为: count = 0 while n > 0: count += n // 5 n //= 5 但是,我们需要验证这种方法是否适用于题目要求。题目要求对于60%的数据n<1000000,对于100%的数据n<2000000000。因此,我们需要一个高效算法,因为n可能达到20亿。 为什么这样计算?因为每隔5个数出现一个5的倍数,每隔25个数出现一个25的倍数(额外多一个5),以此类推。 然而,根据引用[3]提到,阶乘的结果会非常大,直接计算阶乘再数0是不可行的(会溢出且效率低),所以必须用数学方法。 因此,程序可以这样设计: 输入:一个整数n (0<=n<2000000000) 输出:n!尾部连续0个数 步骤: count = 0 while n > 0: n //= 5 # 这里注意:先整除5,然后累加商 count += n 注意:这里循环一次后,n变为n//5,然后用新的n再整除5,直到n为0。这样做的原因是我们计算5的倍数贡献一个5,25的倍数再贡献一个5,125的倍数再贡献一个5,等等。 例如:n=10 第一次:n // 5 = 2, count=2, 然后n=2 第二次:2//5=0, count=2+0=2 所以10!尾部有2个0(实际10!=3628800,确实2个0) 再例如:n=25 第一次:25//5=5, count=5, n=5 第二次:5//5=1, count=5+1=6, n=1 第三次:1//5=0, 结束。所以25!尾部有6个0。 但是,我们需要注意的是,题目要求是连续0。这个算法计算的就是尾部连续0个数,因为因子5的个数决定了连续0个数(而因子2总是足够的)。 因此,我们可以编写程序如下: 注意:输入n可能为00!为1,尾部0个数0。 由于n最大为20亿,所以这个循环次数最多为log5(2000000000)≈13次,非常高效。 代码示例(Python): def count_trailing_zeros(n): count = 0 while n > 0: n //= 5 count += n return count 但是,请注意:题目要求是“从个位数开始向前数连续0个数”,这个算法得到的就是这个结果。 然而,我们再看一下引用[3]中提到的:5555550000000的阶乘有1388887499996个0。我们可以验证一下这个算法的正确性吗? 实际上,我们无法直接计算5555550000000的阶乘,但是我们可以用这个算法计算因子5的个数: 5555550000000 // 5 = 1111110000000 1111110000000 //5 = 222222000000 222222000000//5=44444400000 44444400000//5=8888880000 8888880000//5=1777776000 1777776000//5=355555200 355555200//5=71111040 71111040//5=14222208 14222208//5=2844441(取整) 2844441//5=568888 568888//5=113777 113777//5=22755 22755//5=4551 4551//5=910 910//5=182 182//5=36 36//5=7 7//5=1 1//5=0 然后把这些商加起来:1111110000000+222222000000+44444400000+8888880000+1777776000+355555200+71111040+14222208+2844441+568888+113777+22755+4551+910+182+36+7+1 这个求和很麻烦,但是我们可以写一个小程序来算。不过我们相信这个算法是正确的。 因此,我们只需要按照上述代码实现即可。 但是,注意题目输入范围:n<2000000000(20亿)。我们的算法是O(log n)的,所以没有问题。 所以,程序代码如下: 注意:输入可能有多个测试用例?题目没有说,但按照常规,我们写一个处理单个输入的例子。如果题目要求多次输入,可以循环读取。 下面我们写一个完整的程序(假设一次输入一个n): </think>根据引用内容,计算n阶乘结果尾部连续0个数本质是统计因子5的个数(因为因子2的数量总是多于5)。以下是高效实现的Python代码: ```python def count_trailing_zeros(n): """ 计算n阶乘尾部连续0个数 :param n: 输入的整数 (0 <= n < 2e9) :return: 尾部连续0个数 """ count = 0 while n >= 5: n //= 5 count += n return count # 测试示例 if __name__ == "__main__": n = int(input().strip()) print(count_trailing_zeros(n)) ``` ### 算法说明 1. **数学原理** n! 尾部连续0个数由因子5的个数决定(因子2的数量总是富余)[^1][^2][^4]。 计算公式:$$\text{count} = \sum_{k=1}^{\infty} \left\lfloor \frac{n}{5^k} \right\rfloor$$ 2. **时间复杂度** - 循环次数为 $\lfloor \log_5 n \rfloor$ - 当 $n=2\times10^9$ 时,循环仅需 $\lfloor \log_5(2e9) \rfloor = 13$ 次 - 时间复杂度 $O(\log n)$ 3. **处理流程** - 输入整数 $n$(支持最大 $2\times10^9$) - 循环除以5并累加商值 - 返回累加结果 ### 示例验证 | 输入n | 计算过程 | 输出 | 验证(n!) | |-------|-----------------------------------|------|------------| | 10 | 10//5=2 → 2//5=0 → 累计2 | 2 | 3628800 | | 25 | 25//5=5 → 5//5=1 → 1//5=0 → 累计6| 6 | 1.55e25 | | 0 | 直接返回0 | 0 | 1 | 此算法满足: - 60%数据 $n<10^6$:普通计算机可在 $<0.1ms$ 完成 - 100%数据 $n<2\times10^9$:仍可在 $<0.1ms$ 完成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值