首先,Eratosthenes 的筛子是 O(N*log(log(N))列出所有低于或等于 N 的素数(当 well implemented 时)。
第二:假设您将您的数字分解为具有多重性的 Q 素数,如果不进行筛选,最坏的情况是 O(sqrt(N)) 的过程(最坏的情况:您的数字是素数)。所以你有一张地图:
- p0 -> 多重性 m0
- p1 -> 多重性 m1
- ...
- pQ -> 多重性 mQ
至少乘以 2 个质因数得到多少个除数?
嗯,会有 m0*m1*...mq [更正这里]。为什么?好吧,准备一个由每个因子的幂生成的所有除数的列表(包括 pi0==1),但删除具有 @ 幂的除数987654324@。
- {1,
p0, p02, ...p0m0} 是 m0 生成除数的方法,除 p0 外具有 p0 的幂
- {1,
p1, p12, ...p1m1} 是 m1 生成除数的方式,除 p1 外具有 p1 的幂
- ...
- {1,
pQ, p1Q, ...p1mQ} 是mQ使用pQ 的幂生成除数的方法
具有非素因数的所有组合的数量(因为1 已经包含在每个集合中,并且每个素因数本身被排除在外)将是上述所有子集的笛卡尔积的基数 - 因此产品个别基数,因此m0*m1*...mq
代码 - Java
import java.util.HashMap;
import java.util.Map;
class Example {
static void factor(long N, Map<Long, Short> primesWithMultiplicity) {
// some arg checking and trivial cases
if(N<0) N=-N;
if(0==N) {
throw new IllegalArgumentException(
"Are you kidding me? Every number divides 0, "+
"you really want them all listed?"
);
}
if(1==N) {
primesWithMultiplicity.put(1L,(short)1);
return;
}
// don't try divisors higher than sqrt(N),
// if they would have been detected by their composite-complement
for(long div=2; div*div < N; ) {
short multiplicity=0;
while((N % div)==0) {
multiplicity++;
N /= div; // reduce N
}
if(multiplicity>0) {
primesWithMultiplicity.put(div, multiplicity);
}
div+= (div == 2 ? 1 : 2); // from 2 to 3, but then going only on odd numbers
}
// done.. well almost, if N is prime, then
// trying to divide up to sqrt(N) will lead an empty result. But,
// in this case, N will still be at original value (as opposed
// to being 1 if complete factored)
if(N>1) {
primesWithMultiplicity.put(N, (short)1);
}
}
static int countDistinctCompositePairs(long N) {
HashMap<Long, Short> factoringResults=new HashMap<>();
factor(N, factoringResults);
int ret=1;
for(short multiplicity : factoringResults.values()) {
ret*=multiplicity;
}
return ret/2;
}
static public void main(String[] args) {
System.out.println(countDistinctCompositePairs(24));
}
}