- N!= p1^t1 * p2^t2 * p3^t3* … * pk^tk(其中,p1, p2, … pk为素数,素数可以组成每一个大于1的数码,1< N <= 10^6)
显然可以通过素数线性筛除每一个pi,因为1 < pi <= N,那么问题在于如何求出 ti (即素数pi的个数)。
- 把 N! 分成奇偶两部分 ( 假设N为偶数 )
- N! = 1*2*3*4*5*6*……*N
N!=(2*4*6*8*…N) (1*3*5*7*…(N-1))
N!=2^(N/2)(1*2*3*4*5*6……(N/2))(1*3*5*7*……*(N-1) )
N!=2^(N/2)(N/2)!(1*3*5*……*(N-1)) - 所以N规模的问题转换为N/2规模了,原来求N!含有素数2的个数,等价于求(N/2)!含有素数2的个数加上N/2了。上面是N为偶数的算法,N为奇数时也是一样。
- 递推式f(n, 2) = f(n/2, 2) + n/2,表示n!中2的个数。
- 同理,推出 f(n, p) = f(n/p, p) + n/p,表示n!中素数p的个数。
代码:
int f(int n, int p)
{
if(n==0)
return 0;
return f(n/p) + n/p;
}
练习:
- 问题:N!的末尾有几个0?
- 因为 10 = 2*5,所以只要知道N! 有多少个2和多少个5, 问题就解决了。
Min ( f(n, 2), f(n, 5)) 显然f(n, 2) > f(n, 5),所以只需要求出f(n, 5)。