下面的代码完美无缺,但我希望有人向我解释它背后的数学。基本上,它是如何工作的?
#include <stdio.h>
#include <stdlib.h> /* atoi */
#define min(x, y) (((x) < (y)) ? (x) : (y))
int main(int argc, char* argv[])
{
const int base = 16;
int n,i,j,p,c,noz,k;
n = 7; /* 7! = decimal 5040 or 0x13B0 - 1 trailing zero */
noz = n;
j = base;
/* Why do we start from 2 */
for (i=2; i <= base; i++)
{
if (j % i == 0)
{
p = 0; /* What is p? */
while (j % i== 0)
{
p++;
j /= i;
}
c = 0;
k = n;
/* What is the maths behind this while loop? */
while (k/i > 0)
{
c += k/i;
k /= i;
}
noz = min(noz, c/p);
}
}
printf("%d! has %d trailing zeros\n", n, noz);
return 0;
}
答案 0 :(得分:12)
请注意,问题相当于找到 base 的最大功率,它将 n!分开。
如果基数为素数(我们称之为 p ),我们可以使用theorem from number theory来计算 p 的最大幂
让我们将执行此操作的代码部分提取到函数中:
int maximum_power_of_p_in_fac(int p, int n) {
int mu = 0;
while (n/p > 0) {
mu += n/p;
n /= p;
}
return mu;
}
现在如果 base 是主要力量会发生什么?假设我们有 base = p q 。然后,如果μ是 p 的最高功率,它除以 n!和 r = floor(μ/ q) ,我们有
(p ^ q)^ r = p ^(qr)除p ^μdividesn!
和
(p ^ q)^(r + 1)= p ^(q(r + 1))&gt; = p ^(μ+ 1)不除以n!
所以 r 是n!中 p ^ q 的最大功率。我们也为此写一个函数:
int maximum_power_of_pq_in_fac(int p, int q, int n) {
return maximum_power_of_p_in_fac(p, n) / q;
}
那么如果 base 是一般号码呢?我们说
base = p 1 q 1 p 2 q 2 ... p m q m
(这是 base 的唯一素数因子分解)。然后我们只解决所有p i q i 的问题并采取最小值:
int maximum_power_of_base_in_fac(int base, int n) {
int res = infinity;
for every factor p^q in the prime factorization in base:
res = min(res, maximum_power_of_pq_in_fac(p,q,n));
return res;
}
如何分解 base ?好吧,我们可以使用试验分区,就像您的示例代码一样。我们首先检查2是否是一个主要因素。如果是,我们计算maximum_power_of_pq_in_fac
并将 base 除以2,直到它不再被2整除。然后我们继续下一个候选因素:
void factorize(int base) {
for (int p = 2; p <= base; ++p) {
if (base % p == 0) { // if base is divisible by p, p is a prime factor
int q = 0;
while (base % p == 0) { // compute q and get rid of all the p factors
q++;
base /= p;
}
// do something with factor p^q
}
// proceed with next candidate divisor
}
}
通过仔细检查代码,你会发现它包含了上述所有元素,只是放在一个循环中,这有点令人困惑。
更新:如果您感兴趣,您提供的算法的复杂度为 O(base * log n)。您可以通过略微调整素数因子分解例程轻松地使其成为 O(sqrt(base)* log n):
void factorize(int base) {
for (int p = 2; p*p <= base; ++p) { // only check prime factors up to sqrt(base)
// ... same as before
}
if (base) {
// there is exactly one prime factor > sqrt(base).
// It certainly has multiplicity 1.
// process prime factor base^1
}
}
当然,如果你想加快速度,你可以使用任何其他更复杂的素数因子分解算法。
答案 1 :(得分:1)
基本上,它找到了base
的素数因子,其中i
是素数而i p 是基数因子,然后计算出{{1}因子将存在于n!中,将其除以p,并跟踪i
所有素数因子的最小结果数。
所以回答代码中的问题:
base
c
中i
的因子数量n!