Algoritmo per calcolare il numero di divisori di un dato numero

voti
163

Quale sarebbe l'algoritmo più ottimale (performance-saggio) per calcolare il numero di divisori di un dato numero?

Sarà bello se si potesse fornire pseudocodice o un link a qualche esempio.

EDIT: Tutte le risposte sono state molto utili, grazie. Sto attuazione del crivello di Atkin e poi ho intenzione di usare qualcosa di simile a ciò che Jonathan Leffler indicato. Il link postato da Justin Bozonier ha ulteriori informazioni su quello che volevo.

È pubblicato 21/09/2008 alle 06:44
fonte dall'utente
In altre lingue...                            


28 risposte

voti
1

Si desidera che il crivello di Atkin, descritto qui: http://en.wikipedia.org/wiki/Sieve_of_Atkin

Risposto il 21/09/2008 a 06:53
fonte dall'utente

voti
0

Non si tratta solo di una questione di factoring del numero - la determinazione di tutti i fattori del numero? È quindi possibile decidere se avete bisogno di tutte le combinazioni di uno o più fattori.

Quindi, una possibile procedura 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

E 'quindi a voi per combinare i fattori per determinare il resto della risposta.

Risposto il 21/09/2008 a 06:59
fonte dall'utente

voti
74

Dmitriy è giusto che si vorrà il crivello di Atkin per generare l'elenco primo, ma non credo che si occupa di tutta la questione. Ora che avete una lista di numeri primi è necessario per vedere quanti di questi numeri primi agire come un divisore (e quanto spesso).

Ecco alcuni pitone per l'algo Guardate qui e cercare "Oggetto: la matematica - algoritmo divisori bisogno". Basta contare il numero di elementi nella lista, invece di tornare comunque.

Ecco un Dr. matematica che spiega che cosa esattamente è che devi fare matematicamente.

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

Edit: A proposito, per trovare a, b, c, ecc si vorrà fare ciò che equivale a un algo avido se sto capire questo correttamente. Inizia con il tuo più grande divisore primo e moltiplicarlo per sé fino a quando un ulteriore moltiplicazione supererebbe il numero n. Poi passare alla successiva fattore e volte più basso del precedente Primo ^ numero di volte che è stato moltiplicato per il primo corso e mantenere moltiplicando dal primo fino al prossimo supererà n ... ecc tenere traccia del numero di volte che si moltiplica il divisori insieme ed applicare quei numeri nella formula di cui sopra.

Non al 100% sicuro circa la mia descrizione algo ma se questo non è vero che è qualche cosa di simile.

Risposto il 21/09/2008 a 07:03
fonte dall'utente

voti
-1

Non conosco il metodo più efficiente, ma farei quanto segue:

  • Creare una tabella di numeri primi per trovare tutti i numeri primi minori o uguali alla radice quadrata del numero (Personalmente, mi piacerebbe utilizzare il Crivello di Atkin)
  • Contare tutti i primi inferiore o uguale alla radice quadrata del numero e moltiplicare che da due. Se la radice quadrata del numero è un numero intero, quindi sottrarre uno dalla variabile conteggio.

Dovrebbe funzionare \ o /

Se avete bisogno, posso codice qualcosa domani in C per dimostrare.

Risposto il 21/09/2008 a 07:16
fonte dall'utente

voti
5

Il setaccio di Atkin è una versione ottimizzata del crivello di Eratostene che dà tutti i numeri primi fino ad un dato intero. Si dovrebbe essere in grado di google questo per maggiori dettagli.

Una volta che avete quella lista, si tratta di una semplice questione di dividere il numero per ogni privilegiata per vedere se si tratta di un divisore esatto (vale a dire, il resto è zero).

Le operazioni di base di calcolo i divisori per un numero (n) sono [questo è pseudocodice convertito da codice reale in modo 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
Risposto il 21/09/2008 a 07:36
fonte dall'utente

voti
46

Ci sono un sacco più tecniche al factoring rispetto al vaglio di Atkin. Per esempio supponiamo di voler fattore 5893. Bene il suo sqrt è 76.76 ... Ora cercheremo di scrivere 5893 come prodotto di quadrati. Ben (77 * 77 - 5893) = 36 che è 6 squadrato, così 5893 = 77 * 77 - 6 * 6 = (77 + 6) (77-6) = 83 * 71. Se questo non aveva funzionato avremmo esaminato se 78 * 78-5893 era un quadrato perfetto. E così via. Con questa tecnica è possibile verificare velocemente per i fattori vicino la radice quadrata di n molto più veloce rispetto testando singoli numeri primi. Se si combina questa tecnica per escludere grandi numeri primi con un setaccio, si avrà un metodo di factoring molto meglio che con solo il setaccio.

E questo è solo uno di un gran numero di tecniche che sono state sviluppate. Questo è abbastanza semplice. Ci vorrebbe molto tempo per imparare, per esempio, la teoria dei numeri abbastanza per capire le tecniche di factoring basati su curve ellittiche. (Lo so che esistono. Io non li capisco.)

Quindi a meno che non si tratta di piccoli numeri interi, non vorrei cercare di risolvere questo problema io stesso. Invece mi piacerebbe provare a trovare un modo per usare qualcosa come il PARI libreria che ha già una soluzione altamente efficiente implementata. Con che posso fattorizzare un numero di 40 cifre casuale come 124321342332143213122323434312213424231341 in circa 0,05 secondi. (La sua fattorizzazione, nel caso in cui vi siete chiesti, è 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949 . Sono abbastanza sicuro che non figurava questo fuori usando il setaccio di Atkin ...)

Risposto il 21/09/2008 a 09:47
fonte dall'utente

voti
9

Una risposta alla tua domanda dipende molto dalla dimensione del numero intero. Metodi di piccoli numeri, ad esempio, meno di 100 bit e per i numeri ~ 1000 bit (come quelle utilizzate in crittografia) sono completamente diversi.

Risposto il 21/09/2008 a 19:38
fonte dall'utente

voti
27

Non sono d'accordo che il setaccio della Atkin è la strada da percorrere, perché potrebbe facilmente richiedere più tempo per controllare ogni numero in [1, n] per primalità di quanto lo sarebbe per ridurre il numero da divisioni.

Ecco un po 'di codice che, anche se leggermente hackier, è in genere 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 che sta lavorando codice Python per risolvere questo problema.

Risposto il 23/09/2008 a 02:53
fonte dall'utente

voti
10

Questa domanda interessante è molto più difficile di quanto sembri, e non è stato risposto. La domanda può essere preso in considerazione in 2 domande molto diverse.

1 dato N, trovare la lista L di fattori primi di N

2 data L, calcolare il numero di combinazioni uniche

Tutte le risposte che vedo finora si riferiscono a 1 # e non riescono a parlare non è trattabile per un numero enorme. Per dimensioni modeste N, anche i numeri a 64 bit, è facile; per enormi N, il problema di factoring può prendere "per sempre". crittografia a chiave pubblica dipende da questo.

Domanda # 2 ha bisogno di ulteriori discussioni. Se L contiene solo numeri unici, si tratta di un semplice calcolo utilizzando la formula di combinazione per scegliere oggetti K da n elementi. In realtà, è necessario sommare i risultati di applicare la formula pur variando k da 1 a sizeof (L). Tuttavia, L di solito contengono più occorrenze di più numeri primi. Ad esempio, L = {2,2,2,3,3,5} è la fattorizzazione di N = 360. Ora questo problema è molto difficile!

Riprendendo # 2, data di raccolta C contenente articoli K, in modo tale che punto A ha un 'duplicati, e la voce b ha b' duplicati, ecc quante combinazioni uniche di 1 a k-1 articoli ci sono? Ad esempio, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} deve ciascun ricorrere una sola volta se L = {2,2 , 2,3,3,5}. Ogni così unico sub-collezione è un divisore unica di N moltiplicando le voci del sub-raccolta.

Risposto il 04/11/2008 a 03:52
fonte dall'utente

voti
5

Si potrebbe provare questo. E 'un po' hacker, ma è ragionevolmente veloce.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
Risposto il 18/07/2009 a 04:31
fonte dall'utente

voti
3

Prima di impegnarsi per una soluzione considerare che l'approccio Sieve potrebbe non essere una buona risposta nel caso tipico.

Qualche tempo fa ci fu una questione fondamentale e mi ha fatto un test di tempo - per interi a 32 bit, almeno determinano se fosse il primo era più lento di forza bruta. Ci sono due fattori in corso:

1) Mentre un essere umano vuole un po 'per fare una divisione sono molto veloci sul computer - simile al costo di guardare in alto la risposta.

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

Risposto il 18/07/2009 a 05:11
fonte dall'utente

voti
5

Una volta che hai la fattorizzazione prima, c'è un modo per trovare il numero di divisori. Aggiungere uno a ciascuno degli esponenti su ogni singolo fattore e poi moltiplicare gli esponenti insieme.

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

Aggiungere uno ad ogni esponente di 2 ^ 3 * 3 ^ 3 Moltiplicare esponenti: 3 * 3 = 9

Risposto il 02/02/2010 a 01:28
fonte dall'utente

voti
2

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 di Project Euler 12 su numeri triangolari . La mia soluzione per la maggiore di 500 divisori test è stato eseguito per 309504 microsecondi (~ 0,3 s). 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 era debole contro i numeri primi. Ma dal momento che i numeri triangolari non sono stampati, è servito allo scopo in modo impeccabile. Dal mio profiling, penso che ha fatto abbastanza bene.

Buone vacanze.

Risposto il 30/12/2010 a 22:19
fonte dall'utente

voti
33

@Yasky

La funzione divisori ha un bug nel senso che non funziona correttamente per 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;
}
Risposto il 23/03/2011 a 15:32
fonte dall'utente

voti
6

Una sola riga
che ho pensato molto carefuly sulla tua domanda e ho cercato di scrivere un pezzo estremamente efficiente e performante del codice per stampare tutti i divisori di un dato numero sullo schermo abbiamo bisogno solo una riga di codice! (opzione di utilizzo -STD = c99 durante la compilazione via 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 la ricerca di numeri di divisori è possibile utilizzare la seguente funzione molto 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 si trattano dato numero come un divisore (opera 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;
}

NOTA: due funzioni di cui sopra funziona correttamente per tutti i numero intero positivo tranne numero 1 e 2 quindi è funzionale per tutti i numeri che sono maggiori di 2, ma se avete bisogno di 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 :)

Risposto il 11/11/2011 a 03:59
fonte dall'utente

voti
1

il metodo di numero primo è molto chiaro qui. P [] è un elenco di numero primo minore o uguale al mq = 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  .
Risposto il 10/01/2013 a 00:12
fonte dall'utente

voti
8

Ecco un dritto in avanti O (sqrt (n)) algoritmo. Ho usato questo per risolvere Project 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
    count+=(1 if i**2==n else 0)
    return count  
Risposto il 05/04/2013 a 05:32
fonte dall'utente

voti
1

libri di testo teoria dei numeri chiamano la funzione tau divisore-conteggio. Il primo fatto interessante è che è moltiplicativo, vale a dire. τ (ab) = τ (a) τ (b), quando A e B non hanno fattore comune. (Prova: ogni coppia di divisori di ae b dà un divisore distinto di ab).

Ora notare che per pa Prime, τ (p ** k) = k + 1 (i poteri del p). Così si può facilmente calcolare τ (n) dalla sua fattorizzazione.

Tuttavia fattorizzare grandi numeri può essere lento (la sicurezza di RSA crytopraphy dipende dal prodotto di due numeri primi grandi essendo difficile da Fattorizza). Che suggerisce questo algoritmo ottimizzato

  1. Verifica se il numero è primo (veloce)
  2. Se è così, tornare 2
  3. In caso contrario, fattorizzare il numero (lento se più grandi fattori primi)
  4. Calcolare τ (n) dal fattorizzazione
Risposto il 14/07/2013 a 13:15
fonte dall'utente

voti
1

Quanto segue è un programma C per trovare il numero di divisori di un dato numero.

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

Questo algoritmo funziona correttamente per il numero che sono quadrato perfetto, così come i numeri che non sono quadrato perfetto.

Si noti che l'UpperLimit del ciclo viene impostato radice quadrata del numero di avere l'algoritmo più efficiente.

Si noti che la memorizzazione del UpperLimit in una variabile separata permette di risparmiare anche il tempo, non si dovrebbe chiamare la funzione sqrt nella sezione condizioni del ciclo for, questo consente di risparmiare 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 ciclo è anche possibile utilizzare 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++)
{
    ...
}
Risposto il 19/08/2014 a 14:35
fonte dall'utente

voti
1

Ecco una funzione che ho scritto. è peggio complessità temporale è O (sqrt (n)), miglior tempo d'altra parte è O (log (n)). Ti dà tutti i divisori primi insieme al numero del suo verificarsi.

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;
}
Risposto il 01/12/2014 a 13:02
fonte dall'utente

voti
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;
}
Risposto il 01/12/2014 a 14:01
fonte dall'utente

voti
1

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

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

    }
}
Risposto il 02/12/2014 a 03:25
fonte dall'utente

voti
0

Questo è qualcosa che è venuta in base a Justin risposta. Si 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))
Risposto il 29/11/2015 a 07:30
fonte dall'utente

voti
0

Penso che questo sia quello che stai cercando for.I fa esattamente quello che hai chiesto. Copiarlo e incollarlo in Notepad.Save come * .bat.Run.Enter Number.Multiply il processo attraverso il 2 e questo è il numero di divisors.I fatto che di proposito in modo che il si determinano i divisori più veloce:

Pls notare che il CMD varriable valori di supporto cative sopra 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
Risposto il 07/02/2016 a 21:24
fonte dall'utente

voti
1

@Kendall

Ho provato il codice e fatto alcuni miglioramenti, ora è ancora più veloce. Ho anche provato con @ هومن جاویدپور codice, questo è anche 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;
}
Risposto il 11/11/2016 a 15:32
fonte dall'utente

voti
0

Credo che questo potrà essere utile così come precisa

script.pyton

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

Risposto il 23/01/2017 a 15:57
fonte dall'utente

voti
0

Prova qualcosa in queste righe:

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;
}
Risposto il 23/01/2017 a 16:01
fonte dall'utente

voti
0

È possibile precompute numeri primi fino alla radice sqaure del massimo possibile N e calcolare l'esponente di ogni fattore primo di una serie. Il numero di divisori di n (n = p1 ^ a ^ p2 p3 b ^ c ...) è (a + 1) (b + 1) (c + 1), perché è la stessa di contare il modo di combinare il primo numero di questi fattori (e questo conterà il numero di divisori). Questo è molto veloce se si Precompute i numeri primi

informazioni più dettagliate su questo metodo:

https://mathschallenge.net/library/number/number_of_divisors

https://www.math.upenn.edu/~deturck/m170/wk2/numdivisors.html

http://primes.utm.edu/glossary/xpage/tau.html

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;

int divisors_count(const vector<int>& primes, int n)
{
    int divisors = 1;
    for (int i = 0; i < primes.size(); ++i) {
        int factor = primes[i];
        int factor_exponent = 0;
        while (n % factor == 0) {
            ++factor_exponent;
            n /= factor;
        }
        divisors *= (factor_exponent + 1);
    }
    if (n > 1) 
        return 2*divisors; // prime factor > sqrt(MAX_N)
    return divisors;
}

int main()
{
    const int MAX_N = 1e6;
    int max_factor = sqrt(MAX_N);

    vector<char> prime(max_factor + 1, true);
    for (int i = 3; i <= max_factor; i += 2) {
        if (prime[i]) {
            for (int j = 3*i; j <= max_factor; j += 2*i) {
                prime[j] = false;
            }   
        }
    }

    vector<int> primes;
    primes.reserve(max_factor/2);
    primes.push_back(2);
    for (int i = 3; i <= max_factor; i += 2) {
        if (prime[i]) {
            primes.push_back(i);
        }
    }

    int n;
    while (cin >> n) {
        cout << divisors_count(primes, n) << endl;
    }
}
Risposto il 17/12/2017 a 15:40
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more