找到具有最大除数的1到100范围内的数字

时间:2012-12-04 17:47:24

标签: c algorithm numbers

如何找到除数最多的1到100范围内的最小数字? 我知道一个简单的方法是检查每个数字的除数从1到100并跟踪具有最大除数的数字。 但是有更有效的方法吗?

5 个答案:

答案 0 :(得分:2)

对于1到100之间的每个数字,您可以检查所有数字的倍数并添加除数。根据您检查每个数字的除数的方式,它可以更有效。这是一个执行这个想法的python代码。复杂度为O(N log N)

count=[0]*101
for i in xrange(1,101):
  for j in xrange(1,100/i+1):
    count[i*j]+=1

print max(zip(count,xrange(101))) 

这是C

中的代码
int i,j,count[101];
for(i=1;i<=100;i++) for(j=1;j<=100/i;j++) count[i*j]++;
int max=-1,pos;
for(i=1;i<=100;i++) if(count[i]>=max){
   max=count[i];
   pos=i;
}
printf("%d has %d divisors\n",pos,max);

两个版本都保留了具有最大除数的所有数字中的最大数量。在这种情况下,96有12个除数。

答案 1 :(得分:2)

对于小范围,使用筛子将是我的好。从事实

         r                   r
(1)  n = ∏ p_k^e_k => τ(n) = ∏ (e_k + 1)
        k=1                 k=1
很明显,除数的数量可以很容易地从n的素因子化确定,而τ(m*n) = τ(m) * τ(n)如果gcd(m,n) = 1(即τ是乘法函数< / em>的)。

如果我们知道τ(n)的所有素数因素和n的所有τ(m),我们就可以便宜地计算1 <= m < n。因此

int sieve[limit+1];
// initialise sieve
for(int i = 0; i <= limit; ++i) {
    sieve[i] = i;
}
// find a prime factor for all numbers > 1
int root = sqrt(limit); // limit is supposed to be not too large, so no fixup needed here
for(int p = 2; p <= root; ++p) {
    if (sieve[p] == p) {
        // this means p is prime, mark multiples
        for(int m = p*p; m <= limit; m += p) {
            sieve[m] = p;
        }
}
// Now sieve[n] is a prime factor of n
int p;
for(int n = 2; n <= limit; ++n) {
    if ((p = sieve[n]) == n) {
        // a prime, two divisors
        sieve[n] = 2;
    } else {
        // count the multiplicity of p in n and find the cofactor of p^multiplicity
        int m = 1, q = n;
        do {
            q /= p;
            ++m;
        }while(q % p == 0);
        sieve[n] = m*sieve[q];
    }
}
// Now sieve[n] contains τ(n), the number of divisors of n, look for the maximum
int max_div = 0, max_num = 0;
for(int n = 1; n <= limit; ++n) {
    if (sieve[n] > max_div) {
        max_div = sieve[n];
        max_num = n;
    }
}

N时间内找到最大除数不超过O(N*log log N)的最小数,具有相对较小的常数因子(可以通过单独处理2并且仅标记奇数的奇数倍来进一步减少)素数)。

这是一个简单的蛮力方法,对于小N来说足够快(“小”的解释取决于“足够快”的概念,可以是<= 1000或{{1例如)。

对于较大的边界,这太慢而且内存密集。对于那些,我们需要做更多的分析。

从(1)中,我们可以推导出具有相同结构的素数因子化的所有数字(意味着相同数量<= 1000000的不同素数因子,以及相同的多指数,但可能的顺序不同),所有具有相同数量的除数,最小的是除数

  • 素数因素是r最小素数
  • 指数以降序显示(2表示最大指数,3表示下一个最大指数,...)

因此,我们可以通过考虑所有有限序列找到具有最大除数r的最小数字

<= N

带有属性

e_1 >= e_2 >= ... >= e_r > 0

,所寻求的号码是他们制作的 r N/2 < n(e_1, ..., e_r) = ∏ p_k^e_k <= N k=1 之一。 (如果n(e_1, ..., e_r)为单调非增长有限序列,则添加到n(e_i) <= N/2的1的序列将产生具有更多除数的数字e_1。)

对于与<= N大致成比例的指数生成最大除数。更准确地说,对于固定的1/log p_k,让

r

然后 r T(x_1, ..., x_r) = ∏ (x_k+1) k=1 r F(x_1, ..., x_r) = ∏ p_k^x_k k=1

点的集合T上假设其最大值
{ x : F(x) = N and x_k > 0 for all k }

我们只承认整数指数,这使问题变得复杂,但是偏离比例太远会产生除数比我们在比例附近找到的数字更少的数字。

让我们来说明 r x_k = (log N + ∑ log p_k)/(r * log p_k) - 1 k=1 (它有点太小而不能真正利用比例,但小到足以完全手工完成):

  1. N = 100000r = 1e_1 = 16有17位除数。

  2. n(16) = 2^16 = 65536:设置r = 2x_2 = x_1 * log 2 / log 3,我们获得N = 2^x_1 * 3^x_2 = 2^(2*x_1)。现在让我们看看x_1 ≈ 8.3, x_2 ≈ 5.24接近e_1, e_2会发生什么。

    x_1, x_2

    偏离相称性会更快地减少除数,

    2^7 *3^6 = 93312, τ(2^7 *3^6) =  (7+1)*(6+1) = 56
    2^8 *3^5 = 62208, τ(2^8 *3^5) =  (8+1)*(5+1) = 54
    2^10*3^4 = 82944, τ(2^10*3^4) = (10+1)*(4+1) = 55
    

    所以最接近比例的对没有产生最大的除数,但是具有大的除数的那些是最接近的三个。

  3. 2^11*3^3 = 55296, τ(2^11*3^3) = (11+1)*(3+1) = 48 2^13*3^2 = 73728, τ(2^13*3^2) = (13+1)*(2+1) = 42 2^15*3^1 = 98304, τ(2^15*3^1) = (15+1)*(1+1) = 32 :同样,我们获得r = 3

    x_1 ≈ 5.5, x_2 ≈ 3.5, x_3 ≈ 2.4

    再次,对于接近比例的指数,实现了大的除数计数。

  4. 2^4 *3^3*5^3 = 54000, τ(2^4 *3^3*5^3) = 5*4*4 = 80 2^5 *3^4*5^2 = 64800, τ(2^5 *3^4*5^2) = 6*5*3 = 90 2^7 *3^3*5^2 = 86400, τ(2^7 *3^3*5^2) = 8*4*3 = 96 2^8 *3^2*5^2 = 57600, τ(2^8 *3^2*5^2) = 9*3*3 = 81 2^6 *3^5*5^1 = 77760, τ(2^6 *3^5*5^1) = 7*6*2 = 84 2^7 *3^4*5^1 = 51840, τ(2^7 *3^4*5^1) = 8*5*2 = 80 2^9 *3^3*5^1 = 69120, τ(2^9 *3^3*5^1) = 10*4*2 = 80 2^11*3^2*5^1 = 92160, τ(2^11*3^2*5^1) = 12*3*2 = 72 2^12*3^1*5^1 = 61440, τ(2^12*3^1*5^1) = 13*2*2 = 52 :指数的粗略近似值为r = 4。对于x_1 ≈ 4.15, x_2 ≈ 2.42, x_3 ≈ 1.79, x_4 ≈ 1.48,只有一个选择,

    e_4 = 2

    对于2^3*3^2*5^2*7^2 = 88200, τ(2^3*3^2*5^2*7^2) = 4*3*3*3 = 108 ,我们还有一些选择:

    e_4 = 1
  5. 2^4*3^3*5^2*7^1 = 75600, τ(2^4*3^3*5^2*7^1) = 5*4*3*2 = 120 2^5*3^2*5^2*7^1 = 50400, τ(2^5*3^2*5^2*7^1) = 6*3*3*2 = 108 2^5*3^4*5^1*7^1 = 90720, τ(2^5*3^4*5^1*7^1) = 6*5*2*2 = 120 2^6*3^3*5^1*7^1 = 60480, τ(2^6*3^3*5^1*7^1) = 7*4*2*2 = 112 2^8*3^2*5^1*7^1 = 80640, τ(2^8*3^2*5^1*7^1) = 9*3*2*2 = 108 2^9*3^1*5^1*7^1 = 53760, τ(2^9*3^1*5^1*7^1) = 10*2*2*2 = 80 r = 5。由于x_1 ≈ 3.3, x_2 ≈ 2.1, x_3 ≈ 1.43, x_4 ≈ 1.18, x_5 ≈ 0.96,7和11的指数必须为1,我们才能找到候选者

    2*3*5*7*11 = 2310
  6. 2^2*3^2*5^2*7*11 = 69300, τ(2^2*3^2*5^2*7*11) = 3*3*3*2*2 = 108 2^3*3^3*5^1*7*11 = 83160, τ(2^3*3^3*5^1*7*11) = 4*4*2*2*2 = 128 2^4*3^2*5^1*7*11 = 55440, τ(2^4*3^2*5^1*7*11) = 5*3*2*2*2 = 120 2^6*3^1*5^1*7*11 = 73920, τ(2^6*3^1*5^1*7*11) = 7*2*2*2*2 = 112 :自r = 6以来,此处只有一位候选人,

    2*3*5*7*11*13 = 30030

    并且产生比使用四个或五个素数的最佳候选者更小的除数。

  7. 所以我们调查了28个候选人(并且可能跳过了其中几个),发现最大除数的2^2*3*5*7*11*13 = 60060, τ(60060) = 3*2^5 = 96 是83160(98280是另一个数字,低于100000,有128个除数)。

    这是一个程序,它可以找到最大数量,最大除数不超过给定限制<= 100000几乎是瞬间完成的(没有尝试短切,因为它足够快,就像64位整数一样,任意精度整数,在某些时候会变得有价值):

    < 2^64

答案 2 :(得分:1)

有一种更简单的方式&#34;,但它是理论上的,而不是真正的计算机算法。出现了两种不同的情况 - 一种是因为大多数因素而且#34;你的意思是那个,另一个是因为这些因素必须是唯一的。

在第一种情况下,您只需要认识到,为了最大化因子的数量,每个因子需要尽可能小,即2.因子数最多的数字小于100,因此是最大的2的幂小于100,恰好是64。

如果因子必须是唯一的,那么我们只需使用2,3,5等(素数)直到下一个累积积大于100 - 在这种情况下2 * 3 * 5 = 30就是数字这是最独特的因素。添加第四个因子将使其成为210,因此我们可以尽可能高。

答案 3 :(得分:0)

你可以从Eratosthenes算法的筛子中得到一些想法。只需要从2 * i而不是i * i运行内循环。但是这个算法比O(n ^ 2)

 int a[]=new int[101],max=0,index=-1;
for(i=2;i<=100;i++)
{
if(a[i]==0)
for(j=2*i;j<=100;j+=i)
a[j]++;
if(a[i]>max)
{
index=i;
max=a[i];
}

这为你提供30除数为3.你可以修改内循环,如果你想要答案中的变体

答案 4 :(得分:0)

一种方法是避免奇数..

int mostDivisors(int min,int max)
{
    int i,j,pc=0,cc=0,no=0;
    min=(min%2==0)?min:min+1;//making it even

    for(i=min;i<=max;i+=2)//checking only even numbers
    {
        cc=0;
        for(j=2;j<i;j++)//avoiding dividing by 1 and itself
        {
            if(i%j==0)cc++;
        }
        if(pc<cc)
        {
             no=i;
             pc=cc;
        }
    }
    return no;
}