Performance 一个数中不小于另一个数的除数的个数
有没有什么有效的方法可以找到一个数(比如n)的除数不小于另一个数(比如m)的除数。 n最多可为10^12。 我考虑过筛子算法&然后找到除数的数目。 我的方法检查从m到n的平方根的所有数字。Performance 一个数中不小于另一个数的除数的个数,performance,algorithm,math,prime-factoring,Performance,Algorithm,Math,Prime Factoring,有没有什么有效的方法可以找到一个数(比如n)的除数不小于另一个数(比如m)的除数。 n最多可为10^12。 我考虑过筛子算法&然后找到除数的数目。 我的方法检查从m到n的平方根的所有数字。 但我认为还有另一种方法(有效)可以做到这一点。如果你知道素数因子,就很容易找到一个数的除数;只要考虑所有因素的多重性的所有可能组合 对于小到10^12的n,试用除法应该是一种足够快的因式分解方法,因为您只需检查最大为10^6的潜在因素 编辑:增加关于“所有可能的组合”和按试算法进行保理的讨论 考虑数字2450
但我认为还有另一种方法(有效)可以做到这一点。如果你知道素数因子,就很容易找到一个数的除数;只要考虑所有因素的多重性的所有可能组合 对于小到10^12的n,试用除法应该是一种足够快的因式分解方法,因为您只需检查最大为10^6的潜在因素 编辑:增加关于“所有可能的组合”和按试算法进行保理的讨论 考虑数字24505=5*13*13*29。要枚举其因子,请取所有因子的多重数的所有可能组合:
5^0 * 13^0 * 29^0 = 1
5^0 * 13^0 * 29^1 = 29
5^0 * 13^1 * 29^0 = 13
5^0 * 13^1 * 29^1 = 377
5^0 * 13^2 * 29^0 = 169
5^0 * 13^2 * 29^1 = 4901
5^1 * 13^0 * 29^0 = 5
5^1 * 13^0 * 29^1 = 145
5^1 * 13^1 * 29^0 = 65
5^1 * 13^1 * 29^1 = 1885
5^1 * 13^2 * 29^0 = 845
5^1 * 13^2 * 29^1 = 24505
也不难通过审判庭计算出一个数字。这是算法,你可以把它翻译成你最喜欢的语言;对于10^12以下的数字,速度足够快:
function factors(n)
f = 2
while f * f <= n
if n % f == 0
output f
n = n / f
else
f = f + 1
output n
功能因子(n)
f=2
虽然f*f这取决于应用程序,但如果性能是这样一个问题,我会使用预先生成的哈希表。显然,存储在内存中的10^12个条目可能是不切实际的(或者至少是不可取的),所以我会对第k个素数进行除法测试,只为那些不能被前k个素数整除的数生成哈希表条目
例如,尽管写得粗糙且未经测试,但这应该给您一个想法:
int number = 23456789;
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 0};
int pfactors = 0;
int* prime = primes;
float temp;
// check until we reach the end of the array (0)
while (prime)
{
// divide by prime and check if result is integer
temp = (float)number/*prime;
if (temp == floor(temp))
{
// if so, increment count of prime factors and loop (same prime again!)
pfactors++;
number = (int)temp;
}
else
{
// else try the next prime
prime++;
}
}
// finally, rely on hash table magic
pfactors += pregenerated_hash[number];
下面是一个示例程序,用于计算大于m的n的除数。如果有c除数,则largeDivs()代码在时间O(c)中运行。largeDivs()也以n表示为带因数的数字开始,nset是一个形式(p_i,k_i)对的列表,这样n=乘积{p_i**k_i for i in 1..h}。程序后显示了一些示例输出。check()例程用于演示largeDivs()生成正确的结果。对于较小的m值,check()需要很长时间
def largeDivs(n, nset, m):
p, k = nset[-1]
dd = 0
if len(nset) > 1:
nn, mm = n / p**k, m
for i in range(k+1):
dd += largeDivs(nn, nset[:-1], mm)
mm = (mm + p-1)/p
else:
c, v = k+1, 1
while v<m and c>0:
c, v = c-1, v*p
return c
return dd
def check (n,m,s):
if m<1:
return s
c = 0
for i in range(m,n+1):
if (n%i)==0:
c += 1
return c
tset = [(2,3),(3,2),(11,1),(17,1),(23,2)]
n = s = 1
for i in tset:
s *= 1+i[1]
n *= i[0]**i[1]
print 'n=',n, ' s=',s
m=0
for i in range(8):
print 'm:', m, '\t', largeDivs(n, tset, m), ' Check:',check(n,m,s)
m = 10*m + 5
但是检查所有可能的组合非常耗时!不是吗?不可被第一个k
素数整除的数字的比例变小得相当慢。对于小于20的素数,剩下约17.1%,对于小于100的素数,仍然约12%,对于小于1000的素数,大约8.1%,10000:6.1%。即使丢弃所有可被任何小于100万的素数整除的数字,也需要一个相当大的哈希表。这将使素数介于100万和10^12之间。有37607912018个素数不超过10^12,因此哈希表的条目数将超过3.76*10^10。@DanielFisher-非常有用,谢谢。我将在以后的扫描中删除此答案。不要删除此答案。消极证据也是证据。:)
n= 7122456 s= 144
m: 0 144 Check: 144
m: 5 140 Check: 140
m: 55 124 Check: 124
m: 555 95 Check: 95
m: 5555 61 Check: 61
m: 55555 28 Check: 28
m: 555555 9 Check: 9
m: 5555555 1 Check: 1