让 p1, p2, p3 , … pk 是某个正整数 n 的质因数。通过fundamental theorem of arithmetic,n可以表示为p1e1•p2e2•p3e3• … pkek对于一些正整数e 1, e2, e3, ... ek。此外,任何这样的一组这样的正整数都以这种方式表示一个正整数。
n的每一个因子都可以表示为p1f1•p2f2•p3f3• … pkfk 对于一些整数 fi 其中 0 ≤ fi ≤ ei.
每个fi可以有ei sub>+1 个值从 0 到 ei,所以 n 的因子个数为 (e1+1)•(e2+1)•(e3+1)• … (ek+1)。
由于每个 ei 必须是正数,因此每个 ei em>+1 必须至少为 2。现在我们可以看到,如果 n 有 x 个因子,那么 x 是可表示为 k 个至少为 2 的整数的乘积。相反,如果 x 可表示为 k 个至少为 2 的整数的乘积,该产品为我们提供了 ei 的值,它为我们提供了一个具有 x 的正整数 n 个因数和 k 个质因数。
因此,当且仅当 x 可表示为 的乘积时,存在具有 x 个因数和 k 个质因数的数k 个整数,每个至少为 2。
要对此进行测试,只需将 x 除以素数,例如,尽可能多次除以 2,然后除以 3,再除以 5,等等。一旦 x 除以 k-1 个因子并且结果大于 1,那么我们知道 x 可以表示为 k 的乘积em>k 个整数,每个整数至少为 2(最后一个可能是合数而不是素数,例如 2•3•3•3•35)。如果 x 在我们将其除以 k-1 个因子之前或刚刚达到 1,则不存在这样的数字。
附录
进一步考虑,在测试 x 的因子时,没有必要使用素数作为候选。我们可以简单地遍历整数,测试每个候选 f 是否是 x 的因子。尝试通过首先测试 f 是否为素数来过滤这些将比简单地测试 f 是否是 x 的因子要花费更多的时间。 (这并不是说测试 x 的素数因子的更复杂的方法,例如使用准备好的许多素数表不会更快。)所以下面的代码就足够了。
#include <stdint.h>
/* Return true if and only if there exists a positive integer A with exactly
x factors and exactly k prime factors.
*/
static _Bool DoesAExist(uintmax_t x, uintmax_t k)
{
/* The only positive integer with no prime factors is 1. 1 has exactly
one factor. So, if A must have no prime factors (k is zero), then an A
exists if and only if x is one.
*/
if (k == 0) return x == 1;
/* A number with exactly one prime factor (say p) has at least two factors
(1 and p) and can have any greater number of factors (p^2, p^3,...).
So, if k is one, then an A exists if and only if x is greater than one.
*/
if (k == 1) return 1 < x;
/* Otherwise, an A exists only if x can be expressed as the product of
exactly k factors greater than 1. Test this by dividing x by factors
greater than 1 until either we have divided by k-1 factors (so one
more is needed) or we run out of possible factors.
We start testing factors with two (f = 2).
If we find k factors of x during the loop, we return true.
Otherwise, we continue as long as there might be more factors. (When
f*f <= x is false, we have tested the current value of x by every
integer from two to the square root of x. Then x cannot have any more
factors less than x, because if there is any factorization x = r*s,
either r or s must be less than or equal to the square root of x.)
For each f, as long as it is a factor of the current value of x and we
need more factors, we divide x by it and decrement k to track the
number of factors still required.
*/
for (uintmax_t f = 2; f*f <= x; ++f)
while (x % f == 0)
{
/* As long as f is a factor of x, remove it from x and decrement
the count of factors still needed. If that number reaches one,
then:
If the current value of x exceeds one, it serves as the
last factor, and an A exists, so we return true.
If the current value of x exceeds one, there is no
additional factor, but we still need one, so no A exists,
so we return false.
*/
x /= f;
if (--k <= 1) return 1 < x;
}
/* At this point, we need k more factors for x, and k is greater than one
but x is one or prime, so x does not have enough factors. So no A with
the required properties exists, and we return false.
*/
return 0;
}
#include <stdio.h>
int main(void)
{
printf("False test cases:\n");
printf("%d\n", DoesAExist(0, 0)); // False since each positive integer has at least one factor (1).
printf("%d\n", DoesAExist(2, 0)); // False since no number has two factors and no prime factors.
printf("%d\n", DoesAExist(0, 1)); // False since each positive integer has at least one factor (1).
printf("%d\n", DoesAExist(1, 1)); // False since each positive integer with a prime factor has at least two factors (one and the prime).
printf("%d\n", DoesAExist(2, 2)); // False since each number with two prime factors (p and q) has at least four factors (1, p, q, and pq).
printf("%d\n", DoesAExist(3, 2)); // False since each number with two prime factors (p and q) has at least four factors (1, p, q, and pq).
printf("%d\n", DoesAExist(8, 4));
printf("%d\n", DoesAExist(6, 3));
printf("%d\n", DoesAExist(22, 3));
printf("%d\n", DoesAExist(24, 5));
printf("%d\n", DoesAExist(88, 5));
printf("%d\n", DoesAExist(18, 4));
printf("%d\n", DoesAExist(54, 5));
printf("%d\n", DoesAExist(242, 4));
printf("%d\n", DoesAExist(2662, 5));
printf("True test cases:\n");
printf("%d\n", DoesAExist(1, 0)); // True since 1 has one factor and zero prime factors.
printf("%d\n", DoesAExist(2, 1)); // True since each prime has two factors.
printf("%d\n", DoesAExist(3, 1)); // True since each square of a prime has three factors.
printf("%d\n", DoesAExist(4, 1)); // True since each cube of a prime has three factors.
printf("%d\n", DoesAExist(4, 2)); // True since each number that is the product of two primes (p and q) has four factors (1, p, q, and pq).
printf("%d\n", DoesAExist(8, 2));
printf("%d\n", DoesAExist(8, 3));
printf("%d\n", DoesAExist(6, 2));
printf("%d\n", DoesAExist(22, 2));
printf("%d\n", DoesAExist(24, 2));
printf("%d\n", DoesAExist(24, 3));
printf("%d\n", DoesAExist(24, 4));
printf("%d\n", DoesAExist(88, 2));
printf("%d\n", DoesAExist(88, 3));
printf("%d\n", DoesAExist(88, 4));
printf("%d\n", DoesAExist(18, 2));
printf("%d\n", DoesAExist(18, 3));
printf("%d\n", DoesAExist(54, 2));
printf("%d\n", DoesAExist(54, 3));
printf("%d\n", DoesAExist(54, 4));
printf("%d\n", DoesAExist(242, 2));
printf("%d\n", DoesAExist(242, 3));
printf("%d\n", DoesAExist(2662, 2));
printf("%d\n", DoesAExist(2662, 3));
printf("%d\n", DoesAExist(2662, 4));
}