Algoritmus kiszámítja a száma osztója egy adott számú

szavazat
163

Mi lenne a legoptimálisabb algoritmus (teljesítmény-bölcs), hogy kiszámítja a száma osztója egy adott számot?

Ez lesz jó, ha meg tudná biztosítani pszeudokódokra vagy egy link néhány példa.

EDIT: Minden válasz nagyon segítőkész volt, köszönöm. Én végrehajtása szitán Atkin majd fogom használni valami hasonló ahhoz, amit Jonathan Leffler jelezték. A kapcsolat küldte Justin Bozonier további információkkal rendelkezik, amit akartam.

A kérdést 21/09/2008 06:44
a forrás felhasználó
Más nyelveken...                            


28 válasz

szavazat
1

Azt akarjuk, hogy a szitán Atkin, leírása itt található: http://en.wikipedia.org/wiki/Sieve_of_Atkin

Válaszolt 21/09/2008 06:53
a forrás felhasználó

szavazat
0

Ez nem csak az a kérdés, faktoring száma - meghatározó valamennyi tényezőt a szám? Ekkor eldöntheti, hogy szükséges-e minden kombinációját egy vagy több tényező.

Tehát, az egyik lehetséges algoritmus a következő lenne:

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

Ez akkor rajtad múlik, hogy összekapcsolják a tényezők határozzák meg a többi választ.

Válaszolt 21/09/2008 06:59
a forrás felhasználó

szavazat
74

Dmitriy igaza van, hogy akar majd a szitán Atkin generálni az elsődleges listán, de nem hiszem, hogy gondoskodik az egész kérdést. Most, hogy van egy lista a prímszám akkor be kell látni, hogy hány ilyen prímszám jár, mint egy osztó (és milyen gyakran).

Itt van néhány python az algo Nézz ide , és keressen rá a „Tárgy: matematika - szükség osztók algoritmus”. Csak számolja a tételek számát a listában visszaadása helyett, habár.

Itt egy Dr. Matek , amely elmagyarázza, hogy pontosan mit kell tennie matematikailag.

Lényegében ez csapódik le, hogy ha a szám na következő:
n = a^x * b^y * c^z
(ahol a, b, és c n prime osztója és x, y, és z, hogy hányszor osztó ismétlődik), akkor a teljes szám az összes osztó:
(x + 1) * (y + 1) * (z + 1).

Edit: BTW, hogy megtalálják a, b, c, stb akkor szeretnénk tenni, ami kimeríti a mohó algo ha én megértése ezt helyesen. Kezdje a legnagyobb prímosztója és szorozza meg magát, amíg egy további szaporodását meghaladná az n. Ezután lépjen a következő legalacsonyabb faktor és időpontokban az előző elsődleges ^ hányszor volt szorozva a prime és tartsa megszorozzuk az elsődleges, amíg a következő meg fogja haladni n ... stb Kövesd nyomon a hányszor szaporodnak a osztók együtt, és alkalmazzák ezeket a számokat a fenti képlet.

Nem 100% biztos az algo leírás, de ha ez nem igaz, hogy valami hasonlót.

Válaszolt 21/09/2008 07:03
a forrás felhasználó

szavazat
-1

Nem tudom, hogy a leghatékonyabb módszer, de azt tegye a következőket:

  • Hozzon létre egy táblázatot prímszám találni az összes prímszám kisebb vagy egyenlő a négyzetgyöke számát (Én személy szerint még használja a szitán Atkin)
  • Count az összes prímszám kisebb vagy egyenlő a négyzetgyöke számát és szorozzuk meg kettővel. Ha a négyzetgyöke a szám egész szám, majd vonjuk egyet a számláló változó.

Működnie kell \ o /

Ha szüksége van, tudok kódolni valamit holnap C bizonyítani.

Válaszolt 21/09/2008 07:16
a forrás felhasználó

szavazat
5

A szitán Atkin egy optimalizált változata a szitán Eratosthenes amely minden prímszám akár egy adott szám. Meg kell tudni, hogy a Google ezt részletesebben.

Ha megvan a lista, ez egy egyszerű dolog, hogy ossza meg a számát az egyes elsődleges, hogy ha ez egy pontos osztó (azaz maradék zérus).

Az alapvető lépések kiszámításához osztók számos (n) [ez pszeudokódokra átszámolva igazi kódot, így remélem, nem vezettek be hibák]:

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
Válaszolt 21/09/2008 07:36
a forrás felhasználó

szavazat
46

Van egy csomó több technikát faktoring, mint a szitán Atkin. Például tegyük fel, szeretnénk faktor 5893. Nos az sqrt van 76,76 ... Most megpróbáljuk levelet 5893, mint a termék négyzetek. Nos (77 * 77-5893) = 36, ami 6 négyzetes, így 5893 = 77 * 77-6 * 6 = (77 + 6) (77-6) = 83 * 71. Ha ez nem működött mi volna nézett-e 78 * 78-5893 volt tökéletes négyzet. Stb. Ezzel a technikával gyorsan tesztelni tényezők mellett a négyzetgyöke n sokkal gyorsabb, mint a tesztelés egyes prímszám. Ha össze ezt a technikát, hogy kizárható legyen a nagy prímszám egy szitán, akkor egy sokkal jobb módszer, mint a faktoring a szita egyedül.

És ez csak egy a számos technika, hogy dolgoztak. Ez egy meglehetősen egyszerű. Ez elviszi sokáig megtanulni, mondjuk, elég számelmélet, hogy megértsék a faktoring alapuló technikák elliptikus görbék. (Tudom, hogy léteznek. Nem értem őket.)

Ezért, ha nem foglalkozunk kis egész számok, azt nem próbálja megoldani a problémát magam. Ehelyett azt meg kell találnia a módját, hogy olyasmi, mint a PARI könyvtár, amely már rendelkezik egy rendkívül hatékony megoldás érdekében. Ezzel én is tényező véletlenszerű 40 jegyű számot, mint 124321342332143213122323434312213424231341 körülbelül 0,05 másodperc. (A faktorizációhoz az esetre, ha kíváncsi, van 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949 . Vagyok egészen biztos abban, hogy nem kiderítjük a szitán Atkin ...)

Válaszolt 21/09/2008 09:47
a forrás felhasználó

szavazat
9

A választ a kérdésre nagyban függ a méret a szám. Módszerek a kis számok, például kevesebb mint 100 bit, és a számok ~ 1000 bit (mint például a használt kriptográfiai) teljesen más.

Válaszolt 21/09/2008 19:38
a forrás felhasználó

szavazat
27

Nem értek egyet, hogy a szitán Atkin az út, mert könnyen tarthat ellenőrizni minden számot a [1, n] primality mint ez számának csökkentése által megosztottságot.

Itt van néhány kód, hogy bár kissé hackier, általában sokkal gyorsabb:

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 Ez működik python kódot, hogy megoldja ezt a problémát.

Válaszolt 23/09/2008 02:53
a forrás felhasználó

szavazat
10

Ez érdekes kérdés, hogy sokkal nehezebb, mint amilyennek látszik, és ez még nem érkezett válasz. A kérdés lehet figyelembe venni a 2 nagyon különböző kérdés.

1 adott N, keresse meg a listában L N prime tényezők

2 adott L, számítsuk számos egyedi kombinációk

Minden választ látok eddig lásd # 1, és nem is beszélve, hogy ez nem kezelhetőek a hatalmas számokat. Közepesen méretű N, akár 64 bites számok, könnyű; A hatalmas N, faktoring probléma, hogy „örökre”. A nyilvános kulcsú titkosítás ezen múlik.

Kérdés # 2 szüksége vitát. Ha L amely csak egyedi számokat, ez egy egyszerű számítást a kombináció képlete választja k tárgyak n elem. Igazából, ha kell összefoglalni az eredményeket a készítmény alkalmazása közben változó k 1 és sizeof (L). Azonban az L általában tartalmaznak többszöri előfordulását több prímszám. Például L = {2,2,2,3,3,5} az faktorizációja N = 360 Most ez a probléma elég nehéz!

Újraírása # 2, adott gyűjtemény tartalmazó C k tételek, mint ez az elem egy egy „ismétlődések, és tétel b van b” másolatok, stb, hogy hány egyedi kombinációja az 1-k-1 elem van? Például, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} kell minden egyes egyszer fordul elő, és csak egyszer, ha L = {2,2 , 2,3,3,5}. Minden ilyen egyedi al-gyűjtemény egy egyedi osztója N megszorozzuk a tárgyakat az al-gyűjtemény.

Válaszolt 04/11/2008 03:52
a forrás felhasználó

szavazat
5

Lehet, hogy megpróbál ez. Ez egy kicsit Hackish, de ez eléggé gyors.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
Válaszolt 18/07/2009 04:31
a forrás felhasználó

szavazat
3

Mielőtt kötelezettséget, hogy a megoldás úgy, hogy a Szita megközelítés lehet, hogy nem jó válasz a tipikus eset.

Egy kicsit vissza volt elsődleges kérdés, és én egy időben teszt - 32 bites egészek legalább meghatározására, ha ez elsődleges lassabb volt, mint a nyers erő. Két tényező folyik:

1) Miközben egy ember tart egy darabig, hogy nem egy osztály nagyon gyors a számítógép - hasonlóan a költségek keresi fel a választ.

2) Ha nincs elsődleges tábla lehet, hogy egy hurkot ami teljesen az L1 cache. Ez teszi gyorsabbá.

Válaszolt 18/07/2009 05:11
a forrás felhasználó

szavazat
5

Miután a prímfaktorizáció, van egy módja, hogy megtalálják a számát osztók. Adjunk hozzá egy az egyes művelői minden egyes tényező, majd megszorozzuk a kitevők együtt.

Például: 36 prímfaktorizáció: 2 ^ 2 * 3 ^ 2 osztója: 1, 2, 3, 4, 6, 9, 12, 18, 36 száma osztója: 9

Adjunk hozzá egy minden exponens 2 ^ 3 * 3 ^ 3 Szorzás kitevők: 3 * 3 = 9

Válaszolt 02/02/2010 01:28
a forrás felhasználó

szavazat
2

Osztók Valami látványos: osztódnak teljesen. Ha azt szeretnénk, hogy ellenőrizze a számot osztók egy számot, nez egyértelműen felesleges ha kitölti a teljes spektrumot, 1...n. Még nem végeztünk alapos kutatás erre, de megoldottam Project Euler probléma 12 háromszögszámok . Saját megoldás a nagyobb, majd 500 osztója teszt futott 309.504 mikroszekundum (~ 0.3s). Írtam ezt osztó funkció a megoldást.

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

Ahhoz, hogy minden algoritmus, van egy gyenge pontja. Azt hittem, ez a gyenge ellen prímszám. De mivel háromszögszámok nem nyomtat, akkor elérte a célját hibátlanul. Az én profilalkotás, azt hiszem, nem elég jól.

Kellemes Ünnepeket.

Válaszolt 30/12/2010 22:19
a forrás felhasználó

szavazat
33

@Yasky

Az osztó funkció van egy hibája, hogy nem működik rendesen a tökéletes négyzetek.

Próbáld ki:

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;
}
Válaszolt 23/03/2011 15:32
a forrás felhasználó

szavazat
6

Mindössze egy sort
én gondoltam nagyon hogy gondosan a kérdésről, és megpróbáltam írni egy nagyon hatékony és eredményes, kódrészletet nyomtatás minden osztója egy adott számot a képernyőn van szükségünk, csak egy sor kód! (használat opció -std = C99 fordításnál keresztül 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

megtalálása számok osztóinak akkor a következő nagyon-nagyon gyors funkció (munka rendesen minden egész szám, kivéve az 1. és 2.)

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

vagy ha úgy bánsz adott számot, mint egy osztó (munka rendesen minden egész szám, kivéve az 1. és 2.)

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

Megjegyzés: A fenti két funkció helyesen működik az összes pozitív egész szám, kivéve az 1. számú és 2. ezért funkcionális minden szám, amely nagyobb, mint 2, de ha kell, hogy fedezze az 1. és 2., akkor az alábbi funkciók (egy kicsit lassabb)

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

VAGY

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

A kicsi szép :)

Válaszolt 11/11/2011 03:59
a forrás felhasználó

szavazat
1

prímszám módszer nagyon világos van. P [] van egy lista a prímszám kisebb vagy egyenlő 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  .
Válaszolt 10/01/2013 00:12
a forrás felhasználó

szavazat
8

Itt van egy egyenesen előre O (sqrt (n)) algoritmus. Én ezt megoldani projekt 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  
Válaszolt 05/04/2013 05:32
a forrás felhasználó

szavazat
1

Számelmélet tankönyvek hívja az osztó-számláló funkció tau. Az első érdekes tény, hogy ez az multiplikatív, azaz a. τ (ab) = τ (a) τ (b), amikor a és b nincs közös tényező. (Bizonyítás: mindegyik pár osztója a és b ad egy külön osztója ab).

Most vegye figyelembe, hogy a PA elsődleges, τ (p ** k) = k + 1 (a hatáskörét p). Így könnyen számítani τ (n) saját tényezőkre.

Azonban factorising nagy számban lehet lassú (az RSA biztonsága crytopraphy függ a termék két nagy prímszám, hogy nehezen factorise). Ez azt sugallja, ez optimalizált algoritmus

  1. Test, ha a szám prím (gyors)
  2. Ha igen, vissza 2
  3. Egyébként factorise száma (lassú, ha több nagy prímtényezője)
  4. Számítsuk τ (n) a tényezőkre
Válaszolt 14/07/2013 13:15
a forrás felhasználó

szavazat
1

A következő egy C program, hogy megtalálják a számát osztója egy adott számot.

A komplexitás a fenti algoritmus O (sqrt (n)).

Ez az algoritmus helyesen fog működni a számát, amelyek tökéletes négyzet, valamint a számok, amelyek nem tökéletes négyzet.

Megjegyezzük, hogy a UPPERLIMIT a hurok van beállítva, hogy a Vt szám, hogy az algoritmus a leghatékonyabb.

Megjegyezzük, hogy tárolja a UPPERLIMIT egy külön változót is menti az időt, akkor nem kell hívni a sqrt függvény abban az állapotban részben a for ciklus, ez is elmenti a számítási időt.

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

Ahelyett, hogy a fenti hurok akkor is használja a következő ciklus, amely még hatékonyabb, mert ez megszünteti annak szükségességét, hogy megtalálják a négyzetgyöke a számot.

for(i=2;i*i<=n;i++)
{
    ...
}
Válaszolt 19/08/2014 14:35
a forrás felhasználó

szavazat
1

Itt van egy funkció, amit írtam. ez a legrosszabb futási ideje O (sqrt (n)), a legjobb időt, másrészt az O (log (n)). Ez adja az összes elsődleges osztója számával együtt annak előfordulási.

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;
}
Válaszolt 01/12/2014 13:02
a forrás felhasználó

szavazat
3

Ez egy hatékony megoldás:

#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;
}
Válaszolt 01/12/2014 14:01
a forrás felhasználó

szavazat
1

Ez a legalapvetőbb módja a számítástechnikában az 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);

    }
}
Válaszolt 02/12/2014 03:25
a forrás felhasználó

szavazat
0

Ez olyasmi, kitaláltam alapján Justin választ. Ez lehet szükségük optimalizálás.

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))
Válaszolt 29/11/2015 07:30
a forrás felhasználó

szavazat
0

Azt hiszem, ez az, amit keresünk for.I pontosan mit kértél. Másolás és beillesztés azt Notepad.Save a * .bat.Run.Enter Number.Multiply a folyamat, 2 és amit a számát divisors.I tette, hogy a célból, hogy az ez határozza meg a osztók gyorsabb:

Pls, vegye figyelembe, hogy a CMD varriable vidám támogatás feletti értékek 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
Válaszolt 07/02/2016 21:24
a forrás felhasználó

szavazat
1

@Kendall

Kipróbáltam a kódot, és olyan javításokat, most még gyorsabb. Azt is teszteltük @ هومن جاویدپور kód, ez is gyorsabb, mint a kódot.

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;
}
Válaszolt 11/11/2016 15:32
a forrás felhasználó

szavazat
0

Azt hiszem, ez az egyik lesz kéznél, valamint precíz

script.pyton

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

Válaszolt 23/01/2017 15:57
a forrás felhasználó

szavazat
0

Próbáljon ki valami ezen vonalak mentén:

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;
}
Válaszolt 23/01/2017 16:01
a forrás felhasználó

szavazat
0

Akkor precompute prímszám fel a sqaure gyökér a max lehetséges N és kiszámítja a kitevő minden elsődleges tényező egy számot. A számú osztója n (n = p1 ^ egy p2 ^ b p3 ^ c ...) jelentése (a + 1) (b + 1) (c + 1), mivel ez ugyanaz, mint számolni a módja egyesítik az elsődleges szám ezen tényezők (és ez számít száma osztók). Ez nagyon gyorsan, ha precompute prímszámokat

További részletes információ ezzel a módszerrel:

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;
    }
}
Válaszolt 17/12/2017 15:40
a forrás felhasználó

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