Algoritmo para calcular el número de divisores de un número dado

177

¿Cuál sería el algoritmo más óptimo (en cuanto al rendimiento) para calcular el número de divisores de un número dado?

Sería genial si pudieras proporcionar un pseudocódigo o un enlace a algún ejemplo.

EDITAR: Todas las respuestas han sido muy útiles, gracias. Estoy implementando el Tamiz de Atkin y luego usaré algo similar a lo que Jonathan Leffler indicó. El enlace publicado por Justin Bozonier tiene más información sobre lo que quería.

esquiador
fuente
Teniendo en cuenta que sus requerimientos con el número de factores es vago. Supongo que está buscando el número de divisores primos no únicos porque si no desea que codifique, simplemente escriba un programa para que siempre devuelva 1 si el número para factorizar es uno y 2 si es otra cosa. 0 podría necesitar un cambio ...
Justin Bozonier
@sker: ¿Hay una gama de valores para los que necesita los divisores? Hay muchas formas de calcular los factores, y cada método se adapta mejor a un rango particular.
Ande Turner
2
Aquí hay un problema interesante relacionado projecteuler.net/problem=12
daniloquio
1
El ingenuo Sieve of Atkin, incluso del artículo editado de Wikipedia, nunca será más rápido que un Sieve of Eratosthenes con factor de rueda máximo hasta enormes límites imprácticos, y las versiones segmentadas por página están incluso más a favor del SoE (ver SoE primesieve versus SoA primegen como implementado por el socio de Atkin, Bernstein. Es un conocimiento común e incorrecto de Internet que su estudio demostró que SoA era más rápido, pero limitaron artificialmente la optimización del SoE utilizado para probar esto. Vea mi respuesta de SoA para obtener más explicaciones
GordonBGood

Respuestas:

78

Dmitriy tiene razón en que querrás que el Tamiz de Atkin genere la lista principal, pero no creo que eso se ocupe de todo. Ahora que tiene una lista de números primos, deberá ver cuántos de esos números primos actúan como divisores (y con qué frecuencia).

Aquí hay algo de Python para el algo. Mira aquí y busca "Asunto: matemático - necesita algoritmo de divisores". Sin embargo, solo cuente la cantidad de elementos en la lista en lugar de devolverlos.

Aquí hay un Dr. Math que explica qué es exactamente lo que necesita hacer matemáticamente.

Esencialmente, se reduce a si su número nes:
n = a^x * b^y * c^z
(donde a, byc son los divisores primos de n y x, y, y z son la cantidad de veces que se repite ese divisor), entonces el recuento total de todos los divisores es:
(x + 1) * (y + 1) * (z + 1).

Editar: Por cierto, para encontrar a, b, c, etc., querrás hacer lo que equivale a algo codicioso si lo entiendo correctamente. Comience con su divisor primo más grande y multiplíquelo por sí mismo hasta que una multiplicación adicional exceda el número n. Luego pase al siguiente factor más bajo y multiplicado por el primo anterior ^ número de veces que se multiplicó por el primo actual y siga multiplicándolo por el primo hasta que el próximo exceda n ... etc. Mantenga un registro de la cantidad de veces que multiplica divisores juntos y aplicar esos números en la fórmula anterior.

No estoy 100% seguro acerca de mi descripción de algo, pero si no es así, es algo similar.

Justin Bozonier
fuente
1
Si está factorizando un gran número, ni siquiera quiere tener que mirar la lista principal. ¡Desea eliminar toda una gama de posibilidades lo más rápido posible! Vea mi respuesta para más.
user11318
Me doy cuenta de que esto fue hace 2 años, pero su enlace de Python algo está roto, ¿sabe dónde existe ahora?
jb.
2
Así n = (a^x * b^y * c^z)-(x + 1) * (y + 1) * (z + 1)es la regla
SIslam
1
Como dice @Shashank, el algoritmo en la sección "EDITAR" es incorrecto: suponga que n = 45 = 3 * 3 * 5. El divisor primo más grande es 5, pero multiplicarlo por sí mismo hasta que exceda n haría que el algoritmo informara que tiene 2 copias del factor 5 (ya que 5 * 5 = 25 <45).
j_random_hacker
1
El 'Tamiz de Atkin' tiene una complejidad de tiempo de ejecución de O (N / log (log (N))) en el mejor de los casos. La comprobación de fuerza bruta de todos los divisores posibles de 1 ... Sqrt (n) tiene una complejidad de tiempo de ejecución de O (Sqrt (N)) que es muy superior. ¿Cómo es que esta respuesta ha sido aceptada?
le_m
47

Hay muchas más técnicas para factorizar que el tamiz de Atkin. Por ejemplo, supongamos que queremos factorizar 5893. Bueno, su sqrt es 76.76 ... Ahora intentaremos escribir 5893 como un producto de cuadrados. Bueno (77 * 77 - 5893) = 36, que es 6 al cuadrado, por lo que 5893 = 77 * 77 - 6 * 6 = (77 + 6) (77-6) = 83 * 71. Si eso no hubiera funcionado, habríamos analizado si 78 * 78 - 5893 era un cuadrado perfecto. Y así. Con esta técnica, puede probar rápidamente los factores cercanos a la raíz cuadrada de n mucho más rápido que probando primos individuales. Si combina esta técnica para descartar imprimaciones grandes con un tamiz, tendrá un método de factorización mucho mejor que con el tamiz solo.

Y esta es solo una de las muchas técnicas que se han desarrollado. Este es bastante simple. Le tomaría mucho tiempo aprender, digamos, suficiente teoría de números para comprender las técnicas de factorización basadas en curvas elípticas. (Sé que existen. No los entiendo).

Por lo tanto, a menos que esté tratando con enteros pequeños, no trataría de resolver ese problema yo mismo. En cambio, trataría de encontrar una manera de usar algo como la biblioteca PARI que ya tiene implementada una solución altamente eficiente. Con eso puedo factorizar un número aleatorio de 40 dígitos como 124321342332143213122323434312213424231341 en aproximadamente 0.05 segundos. (Su factorización, en caso de que se lo haya preguntado, es 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949. Estoy bastante seguro de que no resolvió esto usando el tamiz de Atkin ...)

usuario11318
fuente
1
Tu técnica es muy inteligente, pero no me dice cuántos factores tiene el número, ¿verdad?
sker
23
Una vez que tenga la factorización prima, descubrir cuántos factores hay es sencillo. Supongamos que los factores primos son p1, p2, ..., pk y se repiten m1, m2, ..., mk veces. Luego están los factores (1 + m1) (1 + m2) ... (1 + mk).
user11318
Un tamiz interesante es el tamiz cuadrático . Esto utiliza la teoría de números: congruencias cuadráticas y algo de álgebra lineal. Aprendí lo suficiente como para usarlo en un curso de teoría de números de segundo año en la universidad.
Tanner
33

@Yasky

La función de tus divisores tiene un error porque no funciona correctamente para cuadrados perfectos.

Tratar:

int divisors(int x) {
    int limit = x;
    int numberOfDivisors = 0;

    if (x == 1) return 1;

    for (int i = 1; i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            if (limit != i) {
                numberOfDivisors++;
            }
            numberOfDivisors++;
        }
    }

    return numberOfDivisors;
}
Kendall
fuente
66
¿No causará (x% i) una división entre cero cuando i = 0? debería i = 1..limit?
rhu
@rhu Comprobar 0 no tiene sentido de todos modos porque 0 no es un factor de ningún número.
EJoshuaS - Restablece a Monica
29

No estoy de acuerdo con que el tamiz de Atkin sea el camino a seguir, porque podría tomar más tiempo verificar la primalidad de cada número en [1, n] que reducir el número por divisiones.

Aquí hay un código que, aunque ligeramente más pirateado, generalmente es mucho más rápido:

import operator
# A slightly efficient superset of primes.
def PrimesPlus():
  yield 2
  yield 3
  i = 5
  while True:
    yield i
    if i % 6 == 1:
      i += 2
    i += 2
# Returns a dict d with n = product p ^ d[p]
def GetPrimeDecomp(n):
  d = {}
  primes = PrimesPlus()
  for p in primes:
    while n % p == 0:
      n /= p
      d[p] = d.setdefault(p, 0) + 1
    if n == 1:
      return d
def NumberOfDivisors(n):
  d = GetPrimeDecomp(n)
  powers_plus = map(lambda x: x+1, d.values())
  return reduce(operator.mul, powers_plus, 1)

ps Eso está funcionando código python para resolver este problema.

Tyler
fuente
11

Aquí hay un algoritmo directo de O (sqrt (n)). Usé esto para resolver el proyecto euler

def divisors(n):
    count = 2  # accounts for 'n' and '1'
    i = 2
    while i ** 2 < n:
        if n % i == 0:
            count += 2
        i += 1
    if i ** 2 == n:
        count += 1
    return count
Antony Thomas
fuente
pero ¿por qué siempre aumenta el recuento en 2? ... ¿hay un teorema que aplicó?
SummerCode
3
porque estás compitiendo solo hasta sqrt (n). Por ejemplo: si está tratando de encontrar todos los divisores para 36, ​​contará de 2 a 6. Usted sabe que 1 y 36,2 y 18, 3 y 12, 4 y 9, 6,6 son todos divisores y vienen en pares.
Antony Thomas
2
muchas gracias Anthony, entendí ahora: D! un pequeño apéndice: creo que debería tratar el valor sqrt (n) por separado porque por ahora lo tiene en cuenta dos veces en lugar de uno, creo
SummerCode
Si bien O (sqrt (n)) no es tan malo, no es óptimo. calcular la descomposición del factor primo se puede hacer mucho más rápido y es suficiente para calcular el número de divisores.
le_m
En cada iteración, debe calcular i², ¿no sería más rápido comparar i con √n (calculado solo una vez)?
Yukulélé
10

Esta interesante pregunta es mucho más difícil de lo que parece, y no ha sido respondida. La pregunta se puede factorizar en 2 preguntas muy diferentes.

1 dado N, encuentre la lista L de factores primos de N

2 dado L, calcular el número de combinaciones únicas

Todas las respuestas que veo hasta ahora se refieren al número 1 y no mencionan que no es manejable para números enormes. Para N de tamaño moderado, incluso números de 64 bits, es fácil; para N enorme, el problema de factorización puede tomar "para siempre". El cifrado de clave pública depende de esto.

La pregunta # 2 necesita más discusión. Si L contiene solo números únicos, es un cálculo simple que usa la fórmula de combinación para elegir k objetos de n elementos. En realidad, debe sumar los resultados de la aplicación de la fórmula mientras varía k de 1 a sizeof (L). Sin embargo, L generalmente contendrá múltiples ocurrencias de múltiples primos. Por ejemplo, L = {2,2,2,3,3,5} es la factorización de N = 360. ¡Ahora este problema es bastante difícil!

Restableciendo el # 2, dada la colección C que contiene k elementos, de modo que el elemento a tiene 'duplicados, y el elemento b tiene b' duplicados, etc. ¿cuántas combinaciones únicas de 1 a k-1 elementos hay? Por ejemplo, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} deben aparecer una vez y solo una vez si L = {2,2 , 2,3,3,5}. Cada una de estas subcolecciones únicas es un divisor único de N al multiplicar los elementos de la subcolección.

dongilmore
fuente
Aquí hay un enlace a un pseudocódigo para un problema muy similar a 2. answers.google.com/answers/threadview/id/392914.html
mR_fr0g
3
La pregunta # 2 tiene una solución bien conocida. Para una factorización de {p_i, k_i} donde p_ies un factor primo de un número con k_imultiplicidad, el número total de divisores de ese número es (k_1+1)*(k_2+1)*...*(k_n+1). Supongo que ya lo sabes, pero lo escribo para el beneficio de un lector aleatorio aquí.
Will Ness
9

Una respuesta a su pregunta depende en gran medida del tamaño del número entero. Los métodos para números pequeños, por ejemplo, menos de 100 bits, y para números ~ 1000 bits (como los utilizados en criptografía) son completamente diferentes.

jfs
fuente
6

SOLO una línea.
He pensado con mucho cuidado acerca de su pregunta y he tratado de escribir un código altamente eficiente y eficaz. Para imprimir todos los divisores de un número dado en la pantalla, ¡solo necesitamos una línea de código! (use la opción -std = c99 mientras compila a través de gcc)

for(int i=1,n=9;((!(n%i)) && printf("%d is a divisor of %d\n",i,n)) || i<=(n/2);i++);//n is your number

para encontrar números de divisores puede usar la siguiente función muy rápida (funciona correctamente para todos los números enteros excepto 1 y 2)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return counter;
}

o si trata el número dado como un divisor (funciona correctamente para todos los números enteros excepto 1 y 2)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

NOTA: dos funciones anteriores funcionan correctamente para todos los números enteros positivos, excepto los números 1 y 2, por lo que es funcional para todos los números que son mayores que 2, pero si necesita cubrir 1 y 2, puede usar una de las siguientes funciones (un poco más lento)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    if (n==2 || n==1)
    {
    return counter;
    }
    return ++counter;
}

O

int number_of_divisors(int n)
{
    int counter,i;
for(counter=0,i=1;(!(i==n) && !(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

lo pequeño es hermoso :)

هومن جاویدپور
fuente
5

El tamiz de Atkin es una versión optimizada del tamiz de Eratóstenes que da todos los números primos hasta un número entero dado. Debería poder googlear esto para obtener más detalles.

Una vez que tenga esa lista, es simple dividir su número por cada primo para ver si es un divisor exacto (es decir, el resto es cero).

Los pasos básicos para calcular los divisores de un número (n) son [este es un seudocódigo convertido de código real, así que espero no haber introducido errores]:

for z in 1..n:
    prime[z] = false
prime[2] = true;
prime[3] = true;

for x in 1..sqrt(n):
    xx = x * x

    for y in 1..sqrt(n):
        yy = y * y

        z = 4*xx+yy
        if (z <= n) and ((z mod 12 == 1) or (z mod 12 == 5)):
            prime[z] = not prime[z]

        z = z-xx
        if (z <= n) and (z mod 12 == 7):
            prime[z] = not prime[z]

        z = z-yy-yy
        if (z <= n) and (x > y) and (z mod 12 == 11):
            prime[z] = not prime[z]

for z in 5..sqrt(n):
    if prime[z]:
        zz = z*z
        x = zz
        while x <= limit:
            prime[x] = false
            x = x + zz

for z in 2,3,5..n:
    if prime[z]:
        if n modulo z == 0 then print z
paxdiablo
fuente
5

Puedes probar este. Es un poco duro, pero es razonablemente rápido.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
Miguel
fuente
2
Si bien esta función proporciona una descomposición del factor primo de n en un tiempo razonable, es a) no óptima yb) no calcula el número de divisores de un número dado según la pregunta de OP
le_m
Y no funcionará para grandes números debido a su
recurrencia
Aunque esto no es óptimo, y en lugar de contar los factores, en realidad los enumera , la simplicidad y belleza de esto es sorprendente y es razonablemente rápido. ^^
Gaurav Singhal
5

Una vez que tenga la factorización prima, hay una manera de encontrar el número de divisores. Agregue uno a cada uno de los exponentes en cada factor individual y luego multiplique los exponentes juntos.

Por ejemplo: 36 Factorización prima: 2 ^ 2 * 3 ^ 2 Divisores: 1, 2, 3, 4, 6, 9, 12, 18, 36 Número de divisores: 9

Suma uno a cada exponente 2 ^ 3 * 3 ^ 3 Multiplica exponentes: 3 * 3 = 9

D. Williams
fuente
3

Antes de comprometerse con una solución, considere que el enfoque Sieve podría no ser una buena respuesta en el caso típico.

Hace un tiempo hubo una pregunta principal e hice una prueba de tiempo: para enteros de 32 bits, al menos determinar si era primo era más lento que la fuerza bruta. Hay dos factores que suceden:

1) Si bien un humano tarda un tiempo en hacer una división, es muy rápido en la computadora, similar al costo de buscar la respuesta.

2) Si no tiene una tabla principal, puede hacer un bucle que se ejecute completamente en el caché L1. Esto lo hace más rápido.

Loren Pechtel
fuente
3

Esta es una solución eficiente:

#include <iostream>
int main() {
  int num = 20; 
  int numberOfDivisors = 1;

  for (int i = 2; i <= num; i++)
  {
    int exponent = 0;
    while (num % i == 0) {
        exponent++; 
        num /= i;
    }   
    numberOfDivisors *= (exponent+1);
  }

  std::cout << numberOfDivisors << std::endl;
  return 0;
}
Эсмер Амрахлы
fuente
2

Los divisores hacen algo espectacular: se dividen por completo. Si desea comprobar el número de divisores de un número, n, está claro que es redundante para abarcar todo el espectro, 1...n. No he hecho ninguna investigación en profundidad para esto, pero resolví el problema 12 del Proyecto Euler sobre números triangulares . Mi solución para la prueba de más de 500 divisores funcionó durante 309504 microsegundos (~ 0.3s). Escribí esta función divisor para la solución.

int divisors (int x) {
    int limit = x;
    int numberOfDivisors = 1;

    for (int i(0); i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            numberOfDivisors++;
        }
    }

    return numberOfDivisors * 2;
}

Para cada algoritmo, hay un punto débil. Pensé que esto era débil contra los números primos. Pero como los números triangulares no se imprimen, cumplió su propósito sin problemas. Desde mi perfil, creo que lo hizo bastante bien.

Felices vacaciones.

iGbanam
fuente
1
Tendría una división entre 0 en la primera iteración aquí
barfoon
Lamentablemente no. ++ i es diferente de i ++ (lo que daría como resultado un error de división por cero)
iGbanam
Escribí tu función en PHP y la ejecuté: esto es lo que obtuve: i.minus.com/iKzuSXesAkpbp.png
barfoon el
Por alguna extraña razón, esto funcionó perfectamente para mí. oh bueno, mi mal. inicio numberOfDivisorsy el iterador en 1; esto debería deshacerse de la división por cero error
iGbanam
1
Su algoritmo no funciona para cuadrados perfectos. Por ejemplo, devuelve 4 para la entrada x = 4, porque está contando 2 dos veces ... 1, 2, 2, 4. La respuesta debe ser 3: 1,2,4
Michael
1

Desea el Tamiz de Atkin, descrito aquí: http://en.wikipedia.org/wiki/Sieve_of_Atkin

SquareCog
fuente
1
Eso te dará los números primos debajo de tu número dado, pero no hay garantía de que esos números primos sean divisores. (a menos que me falte algo)
Andrew Edgecombe
Es un salto rápido desde aquí para encontrar todos los números primos <sqrt (N) que dividen uniformemente N.
SquareCog
1
Puede ser un salto rápido, pero probar todos los primos <sqrt (N) sigue siendo una mala técnica de factorización, sin importar cuán eficientemente los encuentre. Hay muchas formas de mejorar eso.
user11318
Probar los primos es O (N), encontrar los primos es la parte difícil. Pero incluso con el tamiz no optimizado de eratóstenes, todavía puede encontrar todos los números primos en unos pocos millones en menos de un segundo. Eso cubre cualquier número 64b, y estoy seguro de que no estamos hablando de factorizar cosas de nivel criptográfico aquí
Matthew Scharley,
1

El método del número primo es muy claro aquí. P [] es una lista de números primos menor o igual que sq = sqrt (n);

for (int i = 0 ; i < size && P[i]<=sq ; i++){
          nd = 1;
          while(n%P[i]==0){
               n/=P[i];
               nd++;
               }
          count*=nd;
          if (n==1)break;
          }
      if (n!=1)count*=2;//the confusing line :D :P .

     i will lift the understanding for the reader  .
     i now look forward to a method more optimized  .
abdelkarim
fuente
1

Los libros de texto de teoría de números llaman tau a la función de conteo de divisores. El primer hecho interesante es que es multiplicativo, es decir. τ (ab) = τ (a) τ (b), cuando a y b no tienen un factor común. (Prueba: cada par de divisores de a y b da un divisor distinto de ab).

Ahora tenga en cuenta que para pa prime, τ (p ** k) = k + 1 (las potencias de p). Por lo tanto, puede calcular fácilmente τ (n) a partir de su factorización.

Sin embargo, la factorización de grandes números puede ser lenta (la seguridad de la criptografía RSA depende de que el producto de dos números primos grandes sea difícil de factorizar). Eso sugiere este algoritmo optimizado

  1. Prueba si el número es primo (rápido)
  2. Si es así, devuelve 2
  3. De lo contrario, factorizar el número (lento si hay múltiples factores primos grandes)
  4. Calcule τ (n) a partir de la factorización
Coronel Panic
fuente
1

El siguiente es un programa en C para encontrar el número de divisores de un número dado.

La complejidad del algoritmo anterior es O (sqrt (n)).

Este algoritmo funcionará correctamente para los números que son cuadrados perfectos, así como los números que no son cuadrados perfectos.

Tenga en cuenta que el límite superior del bucle se establece en la raíz cuadrada del número para tener el algoritmo más eficiente.

Tenga en cuenta que almacenar el límite superior en una variable separada también ahorra tiempo, no debe llamar a la función sqrt en la sección de condición del bucle for, esto también ahorra su tiempo computacional.

#include<stdio.h>
#include<math.h>
int main()
{
    int i,n,limit,numberOfDivisors=1;
    printf("Enter the number : ");
    scanf("%d",&n);
    limit=(int)sqrt((double)n);
    for(i=2;i<=limit;i++)
        if(n%i==0)
        {
            if(i!=n/i)
                numberOfDivisors+=2;
            else
                numberOfDivisors++;
        }
    printf("%d\n",numberOfDivisors);
    return 0;
}

En lugar del bucle anterior anterior, también puede usar el siguiente bucle, que es aún más eficiente, ya que elimina la necesidad de encontrar la raíz cuadrada del número.

for(i=2;i*i<=n;i++)
{
    ...
}
La lujosa Kothari
fuente
1

Aquí hay una función que escribí. su peor complejidad es O (sqrt (n)), el mejor momento es O (log (n)). Te da todos los divisores primos junto con el número de su ocurrencia.

public static List<Integer> divisors(n) {   
    ArrayList<Integer> aList = new ArrayList();
    int top_count = (int) Math.round(Math.sqrt(n));
    int new_n = n;

    for (int i = 2; i <= top_count; i++) {
        if (new_n == (new_n / i) * i) {
            aList.add(i);
            new_n = new_n / i;
            top_count = (int) Math.round(Math.sqrt(new_n));
            i = 1;
        }
    }
    aList.add(new_n);
    return aList;
}
Adilli Adil
fuente
No sé qué calcula esta función, pero definitivamente no es la lista de divisores de n.
le_m
1

Esta es la forma más básica de calcular los divisores de números:

class PrintDivisors
{
    public static void main(String args[])
    {

    System.out.println("Enter the number");

    // Create Scanner object for taking input
    Scanner s=new Scanner(System.in);

    // Read an int
    int n=s.nextInt();

        // Loop from 1 to 'n'
        for(int i=1;i<=n;i++)
        {

            // If remainder is 0 when 'n' is divided by 'i',
            if(n%i==0)
            {
            System.out.print(i+", ");
            }
        }

    // Print [not necessary]    
    System.out.print("are divisors of "+n);

    }
}
Malik
fuente
1

@Kendall

Probé su código e hice algunas mejoras, ahora es aún más rápido. También probé con el código @ هومن جاویدپور, esto también es más rápido que su código.

long long int FindDivisors(long long int n) {
  long long int count = 0;
  long long int i, m = (long long int)sqrt(n);
  for(i = 1;i <= m;i++) {
    if(n % i == 0)
      count += 2;
  }
  if(n / m == m && n % m == 0)
    count--;
  return count;
}
as2d3
fuente
0

¿No es solo una cuestión de factorizar el número, determinar todos los factores del número? Luego puede decidir si necesita todas las combinaciones de uno o más factores.

Entonces, un posible algoritmo sería:

factor(N)
    divisor = first_prime
    list_of_factors = { 1 }
    while (N > 1)
        while (N % divisor == 0)
            add divisor to list_of_factors
            N /= divisor
        divisor = next_prime
    return list_of_factors

Depende de usted combinar los factores para determinar el resto de la respuesta.

Jonathan Leffler
fuente
0

Esto es algo que se me ocurrió basado en la respuesta de Justin. Puede requerir alguna optimización.

n=int(input())

a=[]
b=[]

def sieve(n):
    np = n + 1
    s = list(range(np)) 
    s[1] = 0
    sqrtn = int(n**0.5)
    for i in range(2, sqrtn + 1): 
        if s[i]:
            s[i*i: np: i] = [0] * len(range(i*i, np, i))
    return filter(None, s)

k=list(sieve(n))

for i in range(len(k)):
        if n%k[i]==0:
                a.append(k[i])

a.sort()

for i in range(len(a)):
        j=1
        while n%(a[i]**j)==0: 
                j=j+1
        b.append(j-1)

nod=1

for i in range(len(b)):
        nod=nod*(b[i]+1)

print('no.of divisors of {} = {}'.format(n,nod))
winsid96
fuente
0

Creo que esto es lo que estás buscando. Hago exactamente lo que pediste. Cópielo y péguelo en el Bloc de notas. Guárdelo como * .bat. Ejecute. Ingrese el número. Multiplique el proceso por 2 y ese es el número de divisores. Lo hice a propósito para que determine los divisores más rápido:

Tenga en cuenta que una variable CMD no puede admitir valores superiores a 999999999

@echo off

modecon:cols=100 lines=100

:start
title Enter the Number to Determine 
cls
echo Determine a number as a product of 2 numbers
echo.
echo Ex1 : C = A * B
echo Ex2 : 8 = 4 * 2
echo.
echo Max Number length is 9
echo.
echo If there is only 1 proces done  it
echo means the number is a prime number
echo.
echo Prime numbers take time to determine
echo Number not prime are determined fast
echo.

set /p number=Enter Number : 
if %number% GTR 999999999 goto start

echo.
set proces=0
set mindet=0
set procent=0
set B=%Number%

:Determining

set /a mindet=%mindet%+1

if %mindet% GTR %B% goto Results

set /a solution=%number% %%% %mindet%

if %solution% NEQ 0 goto Determining
if %solution% EQU 0 set /a proces=%proces%+1

set /a B=%number% / %mindet%

set /a procent=%mindet%*100/%B%

if %procent% EQU 100 set procent=%procent:~0,3%
if %procent% LSS 100 set procent=%procent:~0,2%
if %procent% LSS 10 set procent=%procent:~0,1%

title Progress : %procent% %%%



if %solution% EQU 0 echo %proces%. %mindet% * %B% = %number%
goto Determining

:Results

title %proces% Results Found
echo.
@pause
goto start
dondon
fuente
882161280 - 1282 divisores
dondon
0

supongo que este será práctico y preciso

script.pyton

>>>factors=[ x for x in range (1,n+1) if n%x==0] print len(factors)

Syed Hissaan
fuente
0

Pruebe algo en este sentido:

int divisors(int myNum) {
    int limit = myNum;
    int divisorCount = 0;
    if (x == 1) 
        return 1;
    for (int i = 1; i < limit; ++i) {
        if (myNum % i == 0) {
            limit = myNum / i;
            if (limit != i)
                divisorCount++;
            divisorCount++;
        }
    }
    return divisorCount;
}
Bryant Jackson
fuente
-1

No conozco el método MÁS eficiente, pero haría lo siguiente:

  • Cree una tabla de números primos para encontrar todos los números primos menores o iguales a la raíz cuadrada del número (Personalmente, usaría el Tamiz de Atkin)
  • Cuente todos los números primos menores o iguales que la raíz cuadrada del número y multiplíquelo por dos. Si la raíz cuadrada del número es un número entero, reste uno de la variable de conteo.

Debería funcionar \ o /

Si lo necesita, puedo codificar algo mañana en C para demostrarlo.

Punto y coma
fuente
2
Estoy confundido. Contar todos los primos menos que la raíz cuadrada de un número no le dará sus divisores ... no cada primo menos que la raíz cuadrada de un número será un divisor para ese número.
Garrett Berg