FCTRL - Factorial的python实现

题目说明

该题目来源于SPOJ:http://www.spoj.com/problems/FCTRL/
大体意思是给定一个数n,求n的阶乘有多少个0结尾。
由于n最大可以是1000000000,笔者初步的算法1,虽然相比整个n遍历一次O(n)时间复杂度减少了80%,但还是无法满足需求;于是有了算法2;
算法2使用递归实现,对于n = 1000000000,只需要递归12次就可以结束,时间复杂度上大大降低。

算法1

0的产生只能是5的倍数乘以2,也就是5*n*2,而偶数的数量在50%左右,因此不缺2,只缺5;因此只需要找到5或5的倍数的个数,就可以知道0的个数了。
定义0计数器count = 0
定义mod5(n)函数返回n能被5整除的次数;
1、n小于5时,count = 0直接返回;
2、n大于等于5时,从5开始遍历n,间隔为5,也就是遍历的顺序是5,10,15,20..,n-n%5;count +=mod5(i)
3、遍历结束后输出count就是0的个数。

算法2

通过算法1可以发现,对于给定的正整数N,去算0的个数,只需要用所有5的倍数乘起来去算即可,定义:
a(n) = 5n
当n>1时,s(n) = s(n-1)*a(n)
推出s(n) = (1*5)*(2*5)(3*5)*...*(n*5) = 5^n * n!
所以对于给定的正整数N,N!当中所有5的乘积可以简化为N! ~  5^(N/5)*(N/5!);
看到上面的式子,就应该想到递归了,完整递归定义:
当n<5时,Z(n)  =  0
当n=5时,Z(n)  =  1
当n>5时,Z(n)  =  n/5 + Z(n/5)


算法2代码实现

def z(n):
	if n < 5:
		return 0
	elif n == 5:
		return 1
	else:
		return z(n/5)+n/5
line = input()
for t in range(line):
	n = input()
	print(z(n))


你可能感兴趣的:(ACM,python)