Algoritme om het aantal delers van een gegeven getal berekenen

stemmen
163

Wat zou de meest optimale algoritme (performance-wise) om het aantal delers van een bepaald aantal te berekenen?

Het zal geweldig zijn als je pseudocode of een link naar een aantal voorbeeld zou kunnen bieden.

EDIT: Alle antwoorden zijn zeer behulpzaam geweest, dank je. Ik ben de uitvoering van de Zeef van Atkin en dan ga ik naar iets wat lijkt op wat Jonathan Leffler aangegeven gebruiken. De link geplaatst door Justin Bozonier heeft meer informatie over wat ik wilde.

De vraag is gesteld op 21/09/2008 om 06:44
bron van user
In andere talen...                            


28 antwoorden

stemmen
1

U wilt dat de zeef van Atkin, hier beschreven: http://en.wikipedia.org/wiki/Sieve_of_Atkin

antwoordde op 21/09/2008 om 06:53
bron van user

stemmen
0

Is dit niet gewoon een kwestie van factoring het nummer - het bepalen van alle factoren van het getal? U kunt dan beslissen of u alle combinaties van één of meer factoren nodig.

Dus, zou een mogelijke algoritme:

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

Het is dan aan jou om de factoren te combineren met de rest van het antwoord te bepalen.

antwoordde op 21/09/2008 om 06:59
bron van user

stemmen
74

Dmitriy heeft gelijk dat u de Zeef van Atkin wilt de prime lijst genereren, maar ik geloof niet dat zorgt voor de hele kwestie. Nu dat u een lijst van priemgetallen die je nodig hebt om te zien hoeveel van die priemgetallen fungeren als een deler (en hoe vaak).

Hier zijn een paar python voor de algo Kijk hier en zoek naar "Subject: wiskunde - behoefte delers algoritme". Gewoon tellen het aantal items in de lijst in plaats van ze echter terug te keren.

Hier is een Dr. Math waarin wordt uitgelegd wat het precies is wat je nodig hebt om wiskundig te doen.

In essentie komt het neer op als uw nummer nis:
n = a^x * b^y * c^z
(waarbij a, b en c n's priemdelers en x, y en z het aantal keren dat deler wordt herhaald) dan het totale aantal voor alle delers:
(x + 1) * (y + 1) * (z + 1).

Edit: BTW, om a, b, c, etc. U zult willen doen wat neerkomt op een gulzige algo als ik het goed heb begrip te vinden. Begin met je grootste priemdeler en vermenigvuldigen met zichzelf tot een verdere vermeerdering zou het aantal n overschrijden. Ga dan naar de volgende laagste factor en tijden de vorige prime ^ aantal malen werd vermenigvuldigd met de huidige prime en houden te vermenigvuldigen met de eerste tot de volgende zal zijn dan n ... enz. Blijf op de hoogte van het aantal keren dat u vermenigvuldigt u het delers elkaar en die nummers toe te passen in de bovenstaande formule.

Niet 100% zeker over mijn algo beschrijving, maar als dat is het niet het is iets dergelijks.

antwoordde op 21/09/2008 om 07:03
bron van user

stemmen
-1

Ik weet niet de meest efficiënte methode, maar ik zou het volgende doen:

  • Maak een tabel van de priemgetallen te vinden van alle priemgetallen kleiner dan of gelijk aan de vierkantswortel van het aantal (Persoonlijk zou ik de Zeef van Atkin te gebruiken)
  • Tel alle priemgetallen kleiner dan of gelijk aan de vierkantswortel van het aantal en vermenigvuldigt met twee. Als de vierkantswortel van het aantal een geheel getal, dan aftrekken van de variabele telling.

Zou moeten werken \ o /

Als u nodig hebt, kan ik iets code morgen in C aan te tonen.

antwoordde op 21/09/2008 om 07:16
bron van user

stemmen
5

De zeef van Atkin is een geoptimaliseerde versie van de zeef van Eratosthenes die alle priemgetallen geeft tot een gegeven integer. Je moet in staat zijn om dit google voor meer informatie.

Zodra u die lijst, is het een eenvoudige zaak om uw nummer delen door elk prime om te zien of het een exacte deler (dat wil zeggen, de rest is nul).

De basisstappen berekenen van de delers voor een aantal (n) [dit wordt omgezet pseudocode van echte code ik hoop ik niet ingevoerd fouten]:

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
antwoordde op 21/09/2008 om 07:36
bron van user

stemmen
46

Er zijn veel meer technieken om factoring dan de zeef van Atkin. Bijvoorbeeld stel dat we willen Well factor 5893. haar sqrt is 76.76 ... Nu gaan we proberen om te schrijven 5893 als een product van pleinen. Putje (77 * 77-5893) = 36 dat 6 kwadraat, dus 5893 = 77 * 77-6 * 6 = (77 + 6) (77-6) = 83 * 71. Als dat niet had gewerkt zouden we hebben gekeken naar de vraag of 78 * 78-5893 was een perfect vierkant. Enzovoorts. Met deze techniek kun je snel testen voor factoren die in de buurt van de vierkantswortel van n veel sneller dan door het testen van individuele priemgetallen. Als u deze techniek voor het uitsluiten van grote priemgetallen met een zeef te combineren, krijg je een veel betere factoring methode te hebben dan met de zeef alleen.

En dit is slechts een van een groot aantal technieken die zijn ontwikkeld. Dit is een vrij eenvoudig. Het zou je een lange tijd om te leren, laten we zeggen, genoeg getaltheorie aan de factoring technieken op basis van elliptische krommen te begrijpen nemen. (Ik weet dat ze bestaan. Ik heb ze niet begrijpen.)

Daarom tenzij je te maken met kleine integers, zou ik niet proberen om dat probleem op te lossen mezelf. In plaats daarvan zou ik proberen een manier om iets als het gebruik vinden PARI bibliotheek die al een zeer efficiënte oplossing geïmplementeerd. Daarmee kan ik een willekeurige 40-cijferig nummer zoals 124321342332143213122323434312213424231341 in ongeveer 0,05 seconden factor. (De factorisatie, voor het geval je je ooit afgevraagd, is 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949 . Ik ben ervan overtuigd dat het dit niet achterhalen met behulp van de zeef van Atkin ...)

antwoordde op 21/09/2008 om 09:47
bron van user

stemmen
9

Een antwoord op uw vraag is sterk afhankelijk van de grootte van de integer. Werkwijzen voor kleine hoeveelheden, bijvoorbeeld minder dan 100 bits, en voor nummers -1000 bit (zoals gebruikt in cryptografie) zijn totaal verschillend.

antwoordde op 21/09/2008 om 19:38
bron van user

stemmen
27

Ik ben het oneens dat de zeef van Atkin is de weg te gaan, omdat het gemakkelijk langer zou kunnen nemen om elk nummer in [1, n] voor primality dan het geval zou het aantal te verminderen door divisies.

Hier is een code die, hoewel iets hackier, is over het algemeen veel sneller:

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 Dat werkt python code om dit probleem op te lossen.

antwoordde op 23/09/2008 om 02:53
bron van user

stemmen
10

Deze interessante vraag is veel moeilijker dan het lijkt, en het is niet beantwoord. De vraag kan worden verwerkt in 2 zeer verschillende vragen.

1 gegeven N, vindt de lijst L priemfactoren N's

2 gegeven L, bereken aantal unieke combinaties

Alle antwoorden die ik zie nu toe verwijzen naar # 1 en niet te vermelden is het niet handelbaar voor enorme aantallen. Voor middelgroot N, ook 64-bits getallen, is het gemakkelijk; voor enorme N, kan de factoring probleem "voor altijd" te nemen. Public key encryptie is afhankelijk van dit.

Vraag # 2 heeft behoefte aan meer discussie. Als L maar unieke nummers bevat, is het een eenvoudige berekening door gecombineerde formule voor het kiezen k objecten uit n eenheden. Eigenlijk moet je de resultaten som toepassing van de formule onder variatie k van 1 tot sizeof (L). Toch zal L bevatten meestal meerdere exemplaren van meerdere primes. Bijvoorbeeld, L = {2,2,2,3,3,5} is de factorisatie van N = 360. Nu dit probleem is heel moeilijk!

Herformuleren # 2, gegeven verzameling C met k items, zodat een punt een 'duplicaten en punt B is b' duplicaten, enz hoeveel unieke combinaties van 1 tot k-1 producten zijn er? Bijvoorbeeld {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} moet elke treedt slechts eenmaal als L = {2,2 , 2,3,3,5}. Elke dergelijke unieke deelverzameling is een uniek deler van N door het vermenigvuldigen van de items in de sub-collectie.

antwoordde op 04/11/2008 om 03:52
bron van user

stemmen
5

Je zou dit opnieuw te proberen. Het is een beetje hackish, maar het is redelijk snel.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
antwoordde op 18/07/2009 om 04:31
bron van user

stemmen
3

Voordat u zich verbinden tot een oplossing van mening dat de Sieve aanpak geen goed antwoord in het typische geval zou kunnen zijn.

Een tijdje terug was er een uitstekende vraag en ik heb een tijd-test - voor 32-bits gehele getallen minstens bepalen of het was prime was langzamer dan brute kracht. Er zijn twee factoren aan de hand:

1) Terwijl een mens duurt een tijdje om een ​​divisie te doen ze zijn zeer snel op de computer - vergelijkbaar met de kosten van het opzoeken van het antwoord.

2) Als u niet beschikt over een toplocatie tafel hebt, kun je een lus die volledig draait op de L1 cache te maken. Dit maakt het sneller.

antwoordde op 18/07/2009 om 05:11
bron van user

stemmen
5

Zodra u de priemfactorisatie, is er een manier om het aantal delers vinden. Voeg één voor elk van de exponenten op elke afzonderlijke factor en vermenigvuldigt de exponenten samen.

Bijvoorbeeld: 36 Prime in factoren: 2 ^ 2 * 3 ^ 2 Delers: 1, 2, 3, 4, 6, 9, 12, 18, 36 Aantal Delers: 9

Voeg een aan elke exponent 2 ^ 3 * 3 ^ 3 Vermenigvuldig exponenten: 3 * 3 = 9

antwoordde op 02/02/2010 om 01:28
bron van user

stemmen
2

Delers doe iets spectaculair: ze volledig verdelen. Als u wilt het aantal delers voor een aantal te controleren, nis het duidelijk is overbodig om het hele spectrum overspannen 1...n. Ik heb geen diepgaand onderzoek gedaan voor, maar ik opgelost Project Euler probleem 12 op driehoeksgetallen . Mijn oplossing voor de meer dan 500 delers -test liep voor 309.504 microseconden (~ 0.3s). Ik schreef dit deler functie voor de oplossing.

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

Elke algoritme is een zwak punt. Ik dacht dat dit zwak tegen priemgetallen was. Maar omdat driehoekige nummers niet worden afgedrukt, het diende zijn doel feilloos. Vanuit mijn profilering, ik denk dat het wel vrij goed.

Fijne vakantie.

antwoordde op 30/12/2010 om 22:19
bron van user

stemmen
33

@Yasky

Uw delers functie heeft een bug in dat het niet goed werkt voor een perfecte pleinen.

Proberen:

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;
}
antwoordde op 23/03/2011 om 15:32
bron van user

stemmen
6

Slechts een regel
: Ik heb zeer carefuly nagedacht over uw vraag en ik heb geprobeerd om een zo efficiënt en performant stukje code te schrijven om alle delers van een bepaald aantal op het scherm we slechts één regel code nodig printen! (gebruik optie std = C99 tijdens het compileren 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

voor het vinden van het aantal delers kunt u de volgende heel erg snel functie (correct werken voor alle geheel getal met uitzondering van 1 en 2) te gebruiken

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

of als u behandelen gegeven getal als een deler (correct werken voor alle geheel getal met uitzondering van 1 en 2)

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

OPMERKING: twee bovenstaande functies correct werkt voor alle positief geheel getal met uitzondering van nummer 1 en 2, dus het is functioneel voor alle getallen die groter zijn dan 2 zijn, maar als je nodig hebt om te dekken 1 en 2, kunt u een van de volgende functies gebruiken (een beetje langzamer)

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

OF

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

klein is mooi :)

antwoordde op 11/11/2011 om 03:59
bron van user

stemmen
1

het priemgetal methode is hier heel duidelijk. P [] is een lijst priemgetal ten hoogste de 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  .
antwoordde op 10/01/2013 om 00:12
bron van user

stemmen
8

Hier is een rechttoe rechtaan O (sqrt (n)) algoritme. Ik gebruikte deze op te lossen 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  
antwoordde op 05/04/2013 om 05:32
bron van user

stemmen
1

Getaltheorie leerboeken bellen met de deler-telfunctie tau. De eerste interessant feit is dat het vermenigvuldigende, dwz. τ (ab) = τ (a) τ (b) wanneer a en b hebben geen gemeenschappelijke factor. (Bewijs: elk paar delers van a en b geeft een duidelijke deler van ab).

Nu er rekening mee dat voor pa prime, τ (p ** k) = k + 1 (de bevoegdheden van p). Zo kunt u gemakkelijk berekenen τ (n) van de ontbinding.

Echter factoren ontbinden grote aantallen kan vertragen (de veiligheid van RSA crytopraphy afhankelijk van het product van twee grote priemgetallen zijn moeilijk te factoriseren) zijn. Dat suggereert deze geoptimaliseerde algoritme

  1. Test of het getal priem (snel)
  2. Als dat zo is, terug 2
  3. Anders factoriseren het aantal (traag als meerdere grote priemfactoren)
  4. Berekenen τ (n) van de ontbinding
antwoordde op 14/07/2013 om 13:15
bron van user

stemmen
1

Het volgende is een C programma om het aantal delers van een bepaald nummer te vinden.

De complexiteit van het bovenstaande algoritme is O (sqrt (n)).

Dit algoritme zal goed werken voor het nummer dat perfect vierkant evenals de nummers die niet perfect vierkant zijn.

Merk op dat de bovengrenstemperatuur van de lus is ingesteld op de vierkantswortel van het aantal aan het algoritme efficiënt zijn.

Merk op dat het opslaan van de UPPERLIMIT in een aparte variabele bespaart ook de tijd, moet je niet bellen met de sqrt functie in de toestand sectie van de lus, dit bespaart ook uw rekentijd.

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

In plaats van de hierboven voor lus kunt u ook de volgende lus die is nog efficiënter te gebruiken, omdat dit verwijdert de noodzaak om de vierkantswortel van het nummer te vinden.

for(i=2;i*i<=n;i++)
{
    ...
}
antwoordde op 19/08/2014 om 14:35
bron van user

stemmen
1

Hier is een functie die ik heb geschreven. is het slechtste tijd complexiteit O (sqrt (n)), de beste tijd aan de andere kant is O (log (n)). Het geeft je alle priemdelers samen met het aantal van haar optreden.

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;
}
antwoordde op 01/12/2014 om 13:02
bron van user

stemmen
3

Dit is een efficiënte oplossing:

#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;
}
antwoordde op 01/12/2014 om 14:01
bron van user

stemmen
1

Dit is de meest eenvoudige manier van het berekenen van het aantal 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);

    }
}
antwoordde op 02/12/2014 om 03:25
bron van user

stemmen
0

Dit is iets wat ik kwam met op basis van Justin antwoord. Het kan enige optimalisatie vereisen.

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))
antwoordde op 29/11/2015 om 07:30
bron van user

stemmen
0

Ik denk dat dit is wat je zoekt for.I doet precies wat je vroeg. Kopieer en plak deze in Notepad.Save als * .bat.Run.Enter Number.Multiply het proces 2 en dat is het aantal divisors.I gemaakt dat met opzet, zodat het deze de delers bepalen sneller:

Pls er rekening mee dat een CMD varriable cant ondersteuning waarden over 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
antwoordde op 07/02/2016 om 21:24
bron van user

stemmen
1

@Kendall

Ik testte de code en maakte een aantal verbeteringen, nu is het nog sneller. Ik heb ook getest met @ هومن جاویدپور code, dit is ook sneller dan zijn code.

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;
}
antwoordde op 11/11/2016 om 15:32
bron van user

stemmen
0

ik denk dat deze zal handig zijn, alsmede nauwkeurige

script.pyton

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

antwoordde op 23/01/2017 om 15:57
bron van user

stemmen
0

Probeer iets langs deze lijnen:

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;
}
antwoordde op 23/01/2017 om 16:01
bron van user

stemmen
0

U kunt priemgetallen precompute tot aan de Sqaure wortel van de maximaal mogelijke N en bereken de exponent van ieder prime factor van een getal. Het aantal delers van n (n = p1 ^ a p2 ^ b p3 ^ c ...) is (a + 1) (b + 1) (c + 1), want het is het zelfde als de telling van de manier van het combineren de prime aantallen van deze factoren (en dit zal het aantal delers te tellen). Dit is erg snel als je precompute de priemgetallen

Meer gedetailleerde informatie over deze methode:

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;
    }
}
antwoordde op 17/12/2017 om 15:40
bron van user

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