Book--阶乘、次方中后缀零、总位数的讨论
2014-06-11 21:29:09
Q1:阶乘中后缀零的计算
显然,n! 前面几项可以写成:1 * 2 * 3 * (2 * 2) * 5 * (2 * 3) * 7 * (2 * 2 * 2) * 9 * (2 * 5).....发现,2 * 5可以使后缀零的个数+1。(而2的个数显然多于5)
结论1: 对于n的阶乘n!,其因式分解中,如果存在一个因子“5”,那么它必然对应着n!末尾的一个“0”。
下面对这个结论进行证明:
(1)当n < 5时, 结论显然成立。
(2)当n >= 5时,令n!= [5k * 5(k-1) * ... * 10 * 5] * a,其中 n = 5k + r (0 <= r <= 4),a是一个不含因子“5”的整数。
对于序列5k, 5(k-1), ..., 10, 5中每一个数5i(1 <= i <= k),都含有因子“5”,并且在区间(5(i-1),5i)(1 <= i <= k)内存在偶数,也就是说,a中存在一个因子“2”与5i相对应。即,这里的k个因子“5”与n!末尾的k个“0”一一对应。
我们进一步把n!表示为:n!= 5^k * k! * a(公式1),其中5^k表示5的k次方。很容易利用(1)和迭代法,得出结论1。
上面证明了n的阶乘n!末尾的“0”与n!的因式分解中的因子“5”是一一对应的。也就是说,计算n的阶乘n!末尾的“0”的个数,可以转换为计算其因式分解中“5”的个数。
令f(x)表示正整数x末尾所含有的“0”的个数, g(x)表示正整数x的因式分解中因子“5”的个数,则利用上面的的结论1和公式1有:
f(n!) = g(n!) = g(5^k * k! * a) = k + g(k!) = k + f(k!)
所以,最终的计算公式为:
当0 < n < 5时,f(n!) = 0;
当n >= 5时,f(n!) = k + f(k!), 其中 k = n / 5(取整)。
更为一般性的讨论:n!在b进制下后缀零的个数
在做Uva10061时,受到上述启发:我们把base拆成素数积的形式,并且找到最大素数maxprime(由于base由这些prime可实现,所以说明只要maxprime存在一个,base即可实现一次,即产生一个后缀零),及其在base中的幂次数n1,所以只要找出maxprime在n!中出现的幂次数n2,后缀0的个数即为:n2 / n1.(取整),而上述十进制中的公式有局限性,不适用于这里,所以这里要单独进行一般性计算。
for (int i = 2; i <= base; ++i) { rbase = 0; while (base % i == 0) { maxp = i;///最大质数 ++rbase;///base质因子分解中最大质数的幂次 base /= i; } }
而这段代码就能得出maxprime,(稍加改进可以输出合数的素数表达式),为什么可以这样扫一遍就OK呢,如果先扫到合数因子呢?幸运的是这是不可能的,因为如果第一个扫到的因子是合数,那么这个合数必定可以分解为比它小的素数,所以,第一个扫到的因子必定是素数!而n可以表示成p1^n1 * p2^n2 * p3^n3 .... pm ^ nm 这样的素数表达式,每扫到一个素因子,就除掉,剩下后面m-1个素数幂积,再继续扫,这样竟然可以保证所扫到的全部是素数因子。
PS:部分借鉴: http://blog.csdn.net/hbxtght/article/details/6515296 http://tech.ddvip.com/2013-11/1385567355206478.html