Algoritmo per calcolare il numero di divisori di un determinato numero


177

Quale sarebbe l'algoritmo più ottimale (dal punto di vista delle prestazioni) per calcolare il numero di divisori di un determinato numero?

Sarebbe bello se potessi fornire uno pseudocodice o un link ad alcuni esempi.

EDIT: Tutte le risposte sono state molto utili, grazie. Sto implementando il setaccio di Atkin e poi userò qualcosa di simile a quello indicato da Jonathan Leffler. Il link pubblicato da Justin Bozonier contiene ulteriori informazioni su ciò che volevo.


Dati i tuoi requisiti con il numero di fattori è vago. Immagino che tu stia cercando il numero di divisori primi non unici perché se non volessi che io codice basta scrivere un programma per restituire sempre 1 se il numero da fattorizzare è uno e 2 se è qualcos'altro. 0 potrebbe aver bisogno di un cambiamento ...
Justin Bozonier,

@sker: esiste una gamma di valori per i quali hai bisogno dei divisori. Esistono molti modi per calcolare i fattori e ogni metodo è più adatto a un determinato intervallo.
Ande Turner,

2
Ecco un problema interessante correlato projecteuler.net/problem=12
daniloquio

1
L'ingenuo setaccio di Atkin nemmeno dall'articolo di Wikipedia modificato non sarà mai più veloce di un setaccio di Eratostene fattorizzato al massimo fino a enormi limiti impraticabili, e le versioni segmentate della pagina sono persino più favorevoli alla SoE (vedi SoE primesieve contro SoA primegen come implementato dal partner di Atkin Bernstein. È risaputo che il loro studio ha dimostrato che il loro studio ha dimostrato SoA più velocemente, ma hanno limitato artificialmente l'ottimizzazione del SoE utilizzato per dimostrarlo. Vedere la mia risposta
SoA

Risposte:


78

Dmitriy ha ragione sul fatto che vorrai che il setaccio di Atkin generi la lista principale, ma non credo che si occupi dell'intera questione. Ora che hai un elenco di numeri primi devi vedere quanti di questi numeri primi fungono da divisori (e con quale frequenza).

Ecco un po 'di pitone per l'algo Guarda qui e cerca "Oggetto: matematica - algoritmo divisori necessari". Basta contare il numero di elementi nell'elenco invece di restituirli comunque.

Ecco un dottor Math che spiega cosa devi fare matematicamente esattamente.

Sostanzialmente si riduce a se il tuo numero nè:
n = a^x * b^y * c^z
(dove a, b e c sono i divisori primi di n e x, ye z sono il numero di volte che il divisore viene ripetuto) quindi il conteggio totale per tutti i divisori è:
(x + 1) * (y + 1) * (z + 1).

Modifica: A proposito, per trovare a, b, c, ecc ti consigliamo di fare ciò che equivale a un avido algo se lo capisco correttamente. Inizia con il tuo più grande divisore primo e moltiplicalo per se stesso fino a quando un'ulteriore moltiplicazione supererebbe il numero n. Quindi passa al fattore più basso successivo e moltiplica il numero primo ^ precedente di volte in cui è stato moltiplicato per il primo corrente e continua a moltiplicare per il primo fino a quando il successivo non supererà n ... ecc. Tieni traccia del numero di volte in cui moltiplichi il divisori insieme e applicare quei numeri nella formula sopra.

Non sono sicuro al 100% della mia descrizione dell'algo, ma in caso contrario è qualcosa di simile.


1
Se stai considerando un numero elevato, non devi nemmeno guardare l'elenco principale. Vuoi eliminare intere gamme di possibilità il più rapidamente possibile! Vedi la mia risposta per di più.
user11318,

Mi rendo conto che è successo 2 anni fa, ma il tuo link algo python è rotto, capisci dove esiste adesso?
jb.

2
Così n = (a^x * b^y * c^z)-(x + 1) * (y + 1) * (z + 1)è la regola
SIslam

1
Come dice @Shashank, l'algoritmo nella sezione "EDIT:" è errato: Supponiamo che n = 45 = 3 * 3 * 5. Il divisore primo più grande è 5, ma moltiplicarlo per se stesso fino a quando non supera n indicherebbe l'algoritmo a segnalare che ha 2 copie del fattore 5 (poiché 5 * 5 = 25 <45).
j_random_hacker,

1
'Sieve of Atkin' ha al massimo una complessità di runtime di O (N / log (log (N))) . La forza bruta che controlla tutti i possibili divisori da 1 ... Sqrt (n) ha una complessità di runtime di O (Sqrt (N)) che è di gran lunga superiore. Come mai questa risposta è stata accettata?
le_m,

47

Ci sono molte più tecniche di factoring rispetto al setaccio di Atkin. Ad esempio supponiamo di voler calcolare il fattore 5893. Beh, la sua sqrt è 76,76 ... Ora proveremo a scrivere 5893 come prodotto dei quadrati. Bene (77 * 77 - 5893) = 36 che è 6 quadrati, quindi 5893 = 77 * 77 - 6 * 6 = (77 + 6) (77-6) = 83 * 71. Se ciò non avesse funzionato avremmo verificato se il 78 * 78 - 5893 fosse un quadrato perfetto. E così via. Con questa tecnica è possibile verificare rapidamente i fattori vicino alla radice quadrata di n molto più velocemente rispetto al test dei singoli numeri primi. Se combini questa tecnica per escludere numeri primi grandi con un setaccio, avrai un metodo di factoring molto migliore rispetto al solo setaccio.

E questa è solo una delle tante tecniche sviluppate. Questo è abbastanza semplice. Ci vorrebbe molto tempo per imparare, diciamo, abbastanza teoria dei numeri per capire le tecniche di factoring basate su curve ellittiche. (So ​​che esistono. Non li capisco.)

Pertanto, a meno che tu non abbia a che fare con piccoli numeri interi, non proverei a risolvere questo problema da solo. Invece, proverei a trovare un modo per usare qualcosa come la libreria PARI che ha già implementato una soluzione altamente efficiente. Con ciò posso calcolare un numero casuale di 40 cifre come 124321342332143213122323434312213424231341 in circa 0,05 secondi. (La sua fattorizzazione, nel caso te lo chiedessi, è 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949. Sono abbastanza fiducioso che non l'abbia capito usando il setaccio di Atkin ...)


1
La tua tecnica è molto intelligente, ma non mi dice quanti fattori ha il numero, vero?
sker

23
Una volta che hai la fattorizzazione primaria, capire quanti fattori ci sono è semplice. Supponiamo che i fattori primi siano p1, p2, ..., pk e vengano ripetuti m1, m2, ..., mk volte. Quindi ci sono (1 + m1) (1 + m2) ... (1 + mk) fattori.
user11318,

Un setaccio interessante è il setaccio quadratico . Questo usa la teoria dei numeri - congruenze quadratiche e qualche algebra lineare. Ho imparato abbastanza da usarlo in un corso di teoria dei numeri del 2 ° anno all'università.
Tanner,

33

@Yasky

La funzione dei tuoi divisori ha un bug in quanto non funziona correttamente per i quadrati perfetti.

Provare:

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;
}

6
(X% i) non causerà una divisione per zero quando i = 0? dovrei = 1..limito?
rhu,

@rhu Il controllo di 0 è comunque inutile perché 0 non è un fattore di nessun numero.
EJoshuaS - Ripristina Monica il

29

Non sono d'accordo sul fatto che il setaccio di Atkin sia la strada da percorrere, perché potrebbe richiedere più tempo per controllare la primalità di ogni numero in [1, n] di quanto non ridurrebbe il numero di divisioni.

Ecco un po 'di codice che, sebbene leggermente hacker, è generalmente molto più veloce:

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 Funziona con il codice Python per risolvere questo problema.


11

Ecco un algoritmo O (sqrt (n)) semplice. L'ho usato per risolvere il progetto 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

ma perché aumenti sempre il conteggio di 2? ... c'è un teorema che hai applicato?
SummerCode

3
perché sei conting solo fino a sqrt (n). Ad esempio: se stai cercando di trovare tutti i divisori per 36 - conterai da 2 a 6. Sai che 1 e 36,2 e 18, 3 e 12, 4 e 9, 6,6 sono tutti divisori e vengono in coppia.
Antony Thomas,

2
grazie mille Anthony, ho capito subito: D! un piccolo addendum: penso che dovrebbe trattare separatamente il valore sqrt (n) perché per ora lo prende in considerazione due volte invece di uno, penso
SummerCode

Mentre O (sqrt (n)) non è troppo male, non è ottimale. calcolare la decomposizione del fattore primo può essere fatto molto più velocemente ed è sufficiente per calcolare il numero di divisori.
le_m,

Ad ogni iterazione, devi calcolare i², non sarebbe più veloce confrontare i con √n (calcolato solo una volta)?
Yukulélé,

10

Questa domanda interessante è molto più difficile di quanto sembri e non ha ricevuto risposta. La domanda può essere considerata in 2 domande molto diverse.

1 dato N, trova l'elenco L dei fattori primi di N

2 dato L, calcola il numero di combinazioni uniche

Tutte le risposte che vedo finora si riferiscono al n. 1 e non menziono che non è trattabile per numeri enormi. Per N di dimensioni moderate, anche numeri a 64 bit, è facile; per l'enorme N, il problema del factoring può richiedere "per sempre". La crittografia della chiave pubblica dipende da questo.

La domanda n. 2 necessita di ulteriori discussioni. Se L contiene solo numeri univoci, è un semplice calcolo che utilizza la formula di combinazione per scegliere k oggetti da n elementi. In realtà, è necessario sommare i risultati dall'applicazione della formula variando k da 1 a sizeof (L). Tuttavia, L conterrà di solito più occorrenze di più numeri primi. Ad esempio, L = {2,2,2,3,3,5} è la fattorizzazione di N = 360. Ora questo problema è abbastanza difficile!

Riaffermando # 2, data la raccolta C contenente k articoli, tale che l'articolo a ha un 'duplicato e l'articolo b ha b' duplicati, ecc. Quante combinazioni uniche da 1 a k-1 ci sono? Ad esempio, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} devono verificarsi ciascuno una volta e una sola volta se L = {2,2 , 2,3,3,5}. Ciascuna di tali sotto-collezioni è un unico divisore di N moltiplicando gli articoli nella sotto-raccolta.


Ecco un link ad alcuni pseudo-codice per un problema molto simile a 2. risposte.google.com/answers/threadview/id/392914.html
mR_fr0g

3
La domanda n. 2 ha una soluzione ben nota. Per una fattorizzazione di {p_i, k_i} dove p_iè un fattore primo di un numero con k_imolteplicità, il numero totale di divisori di quel numero è (k_1+1)*(k_2+1)*...*(k_n+1). Immagino che tu lo sappia ormai, ma lo scrivo per il beneficio se un lettore casuale qui.
Will Ness,


6

Solo una riga
ho pensato molto attentamente alla tua domanda e ho cercato di scrivere un pezzo di codice altamente efficiente e performante Per stampare tutti i divisori di un dato numero sullo schermo abbiamo bisogno di una sola riga di codice! (usa l'opzione -std = c99 durante la compilazione tramite 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

per trovare numeri di divisori puoi usare la seguente funzione molto veloce (funziona correttamente per tutti i numeri interi tranne 1 e 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 se tratti un dato numero come un divisore (funziona correttamente per tutto il numero intero tranne 1 e 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: due funzioni sopra funzionano correttamente per tutti i numeri interi positivi tranne i numeri 1 e 2, quindi sono funzionali a tutti i numeri maggiori di 2 ma se è necessario coprire 1 e 2, è possibile utilizzare una delle seguenti funzioni (un po ' Più lentamente)

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;
}

piccolo è bello :)


5

Il setaccio di Atkin è una versione ottimizzata del setaccio di Eratostene che fornisce tutti i numeri primi fino a un dato intero. Dovresti essere in grado di cercarlo su Google per maggiori dettagli.

Una volta che hai quell'elenco, è semplice dividere il tuo numero per ogni numero primo per vedere se è un divisore esatto (cioè, il resto è zero).

I passaggi di base che calcolano i divisori per un numero (n) sono [questo è pseudocodice convertito da codice reale, quindi spero di non aver introdotto errori]:

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

5

Potresti provare questo. È un po 'hacker, ma è abbastanza veloce.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)

2
Mentre questa funzione fornisce una decomposizione del fattore primo di n in un tempo ragionevole, è a) non ottimale eb) non calcola il numero di divisori di un dato numero secondo la domanda di OP
le_m

E non funzionerà per grandi numeri a causa della sua ricorsione
whackamadoodle3000

Sebbene questo non sia ottimale, e piuttosto che contare i fattori, in realtà li elenca , la semplicità e la bellezza di questo è sorprendente ed è ragionevolmente veloce. ^^
Gaurav Singhal

5

Una volta ottenuta la scomposizione in fattori primi, c'è un modo per trovare il numero di divisori. Aggiungi uno a ciascuno degli esponenti su ogni singolo fattore e quindi moltiplica gli esponenti insieme.

Ad esempio: 36 Fattorizzazione Prime: 2 ^ 2 * 3 ^ 2 Divisori: 1, 2, 3, 4, 6, 9, 12, 18, 36 Numero di divisori: 9

Aggiungine uno a ciascun esponente 2 ^ 3 * 3 ^ 3 Moltiplica gli esponenti: 3 * 3 = 9


3

Prima di impegnarti in una soluzione, considera che l'approccio Sieve potrebbe non essere una buona risposta nel caso tipico.

Qualche tempo fa c'era una domanda principale e ho fatto un test del tempo - per gli interi a 32 bit almeno determinare se era primo era più lento della forza bruta. Ci sono due fattori in corso:

1) Mentre un essere umano impiega un po 'di tempo a fare una divisione, è molto veloce sul computer, simile al costo di cercare la risposta.

2) Se non si dispone di una tabella principale, è possibile creare un ciclo che viene eseguito interamente nella cache L1. Questo lo rende più veloce.


3

Questa è una soluzione efficiente:

#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;
}

2

I divisori fanno qualcosa di spettacolare: si dividono completamente. Se si desidera controllare il numero di divisori per un numero, nè chiaramente ridondante per coprire l'intero spettro, 1...n. Non ho fatto alcuna ricerca approfondita per questo, ma ho risolto il problema del Progetto Euler 12 sui numeri triangolari . La mia soluzione per il test superiore a 500 divisori è stata eseguita per 309504 microsecondi (~ 0,3 secondi). Ho scritto questa funzione divisore per la soluzione.

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;
}

Per ogni algoritmo, c'è un punto debole. Ho pensato che questo fosse debole rispetto ai numeri primi. Ma poiché i numeri triangolari non sono stampati, ha funzionato perfettamente. Dal mio profilo, penso che sia andato abbastanza bene.

Buone vacanze.


1
Avresti una divisione per 0 sulla prima iterazione qui
barfoon

Sfortunatamente no. ++ i è diverso da i ++ (il che comporterebbe un errore di divisione per zero)
iGbanam

Ho scritto la tua funzione in PHP e l'ho eseguita - ecco cosa ho ottenuto - i.minus.com/iKzuSXesAkpbp.png
barfoon

per qualche strana ragione, questo ha funzionato perfettamente per me. oh bene, mio ​​male. start numberOfDivisorse l'iteratore su 1; questo dovrebbe eliminare la divisione per zero errori
iGbanam,

1
Il tuo algoritmo non funziona per quadrati perfetti. Ad esempio, restituisce 4 per l'ingresso x = 4, perché conta due volte 2 ... 1, 2, 2, 4. La risposta dovrebbe essere 3: 1,2,4
Michael

1

Vuoi il setaccio di Atkin, descritto qui: http://en.wikipedia.org/wiki/Sieve_of_Atkin


1
Ti porterà i numeri primi al di sotto del tuo numero dato - ma non c'è garanzia che quei numeri primi saranno divisori? (a meno che non mi manchi qualcosa)
Andrew Edgecombe,

Da qui è un salto veloce trovare tutti i numeri primi <sqrt (N) che dividono uniformemente N.
SquareCog

1
Potrebbe essere un salto veloce, ma testare tutti i numeri primi <sqrt (N) è ancora una cattiva tecnica di factoring, non importa quanto li trovi in ​​modo efficiente. Ci sono molti modi per migliorarlo.
user11318,

Testare i numeri primi è O (N), sta trovando i numeri primi che è la parte difficile. Ma anche con il setaccio non ottimizzato di eratostene, puoi ancora trovare tutti i numeri primi sotto i pochi milioni in meno di un secondo. Questo copre qualsiasi numero 64b, e sono sicuro che non stiamo parlando di roba a livello di
criptovaluta

1

il metodo dei numeri primi è molto chiaro qui. P [] è un elenco di numeri primi minori o uguali a 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  .

1

I manuali di teoria dei numeri chiamano tau la funzione di conteggio dei divisori. Il primo fatto interessante è che è moltiplicativo, cioè. τ (ab) = τ (a) τ (b), quando aeb non hanno alcun fattore comune. (Prova: ogni coppia di divisori di aeb dà un distinto divisore di ab).

Ora nota che per pa prime, τ (p ** k) = k + 1 (i poteri di p). Quindi puoi facilmente calcolare τ (n) dalla sua fattorizzazione.

Tuttavia, la scomposizione in fattori di grandi numeri può essere lenta (la sicurezza della crtoprofia RSA dipende dal fatto che il prodotto di due numeri primi di grandi dimensioni è difficile da scomporre). Ciò suggerisce questo algoritmo ottimizzato

  1. Verifica se il numero è primo (veloce)
  2. In tal caso, restituire 2
  3. Altrimenti, fattorizza il numero (lento se multipli fattori primi di grandi dimensioni)
  4. Calcola τ (n) dalla fattorizzazione

1

Di seguito è riportato un programma C per trovare il numero di divisori di un determinato numero.

La complessità dell'algoritmo sopra è O (sqrt (n)).

Questo algoritmo funzionerà correttamente per il numero che è un quadrato perfetto, nonché per i numeri che non sono un quadrato perfetto.

Si noti che il limite superiore del loop è impostato sulla radice quadrata del numero per avere l'algoritmo più efficiente.

Notare che la memorizzazione di upperlimit in una variabile separata consente anche di risparmiare tempo, non si dovrebbe chiamare la funzione sqrt nella sezione condizione del ciclo for, questo risparmia anche il tempo di calcolo.

#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;
}

Invece di quanto sopra per il ciclo puoi anche usare il seguente ciclo che è ancora più efficiente in quanto elimina la necessità di trovare la radice quadrata del numero.

for(i=2;i*i<=n;i++)
{
    ...
}

1

Ecco una funzione che ho scritto. il tempo peggiore è la complessità O (sqrt (n)), il miglior tempo invece è O (log (n)). Ti dà tutti i divisori primi insieme al numero della sua occorrenza.

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;
}

Non so che cosa calcola questa funzione, ma sicuramente non è la lista dei divisori di n.
le_m,

1

Questo è il modo più semplice per calcolare il numero di divissors:

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);

    }
}

1

@Kendall

Ho testato il tuo codice e apportato alcuni miglioramenti, ora è ancora più veloce. Ho anche testato con il codice @ هومن جاویدپور, anche questo è più veloce del suo codice.

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;
}

0

Non è solo una questione di factoring del numero - determinare tutti i fattori del numero? È quindi possibile decidere se sono necessarie tutte le combinazioni di uno o più fattori.

Quindi, un possibile algoritmo sarebbe:

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

Spetta quindi a te combinare i fattori per determinare il resto della risposta.


0

Questa è una cosa che mi è venuta in base alla risposta di Justin. Potrebbe richiedere qualche ottimizzazione.

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))

0

Penso che questo sia quello che stai cercando. Faccio esattamente quello che hai chiesto. Copia e incolla nel Blocco note. Salva come * .bat.Run.Inserisci numero. Moltiplica il processo per 2 e questo è il numero di divisori. L'ho fatto apposta in modo che determini i divisori più velocemente:

Si prega di notare che un CMD non può supportare valori superiori 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

882161280-1282 divisori
dondon

0

suppongo che questo sarà utile e preciso

script.pyton

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


0

Prova qualcosa del genere:

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;
}

-1

Non conosco il metodo PIÙ efficiente, ma farei quanto segue:

  • Crea una tabella di numeri primi per trovare tutti i numeri primi uguali o uguali alla radice quadrata del numero (Personalmente, userei il setaccio di Atkin)
  • Contare tutti i numeri primi inferiori o uguali alla radice quadrata del numero e moltiplicarlo per due. Se la radice quadrata del numero è un numero intero, sottrarre uno dalla variabile di conteggio.

Dovrebbe funzionare \ o /

Se hai bisogno, posso codificare qualcosa domani in C per dimostrarlo.


2
Non ho capito bene. Contare tutti i numeri primi in meno della radice quadrata di un numero non ti darà i suoi divisori ... non tutti i numeri primi in meno della radice quadrata di un numero saranno divisori per quel numero.
Garrett Berg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.