Algoritmus pro výpočet počtu dělitelů daným počtem

hlasů
163

Co by bylo nejoptimálnější algoritmus (výkon-moudrý) pro výpočet počtu dělitele daného čísla?

Bude to skvělé, kdybyste mohli poskytnout pseudocode nebo odkaz na nějaký příklad.

EDIT: Všechny odpovědi byly velmi užitečné, děkuji. Já jsem se provádí sítem Atkin a pak budu používat něco podobného tomu, co Jonathan Leffler je uvedeno. Spojení odeslal Justin Bozonier má další informace o tom, co jsem chtěl.

Položena 21/09/2008 v 06:44
zdroj uživatelem
V jiných jazycích...                            


28 odpovědí

hlasů
1

Chcete sítem Atkin, zde popsán: http://en.wikipedia.org/wiki/Sieve_of_Atkin

Odpovězeno 21/09/2008 v 06:53
zdroj uživatelem

hlasů
0

Není to jen otázka factoringových počet - určení všechny faktory čísla? Pak můžete rozhodnout, zda budete potřebovat všechny kombinace jednoho nebo více faktorů.

Takže jedním z možných algoritmus bude vypadat následovně:

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

Je tedy na vás, abyste kombinovat faktory určující zbytek odpovědi.

Odpovězeno 21/09/2008 v 06:59
zdroj uživatelem

hlasů
74

Dmitriy má pravdu, že budete chtít sítem Atkin generovat primární seznam, ale nevěřím, že se postará o celé problematice. Nyní, když máte seznam prvočísel, budete muset zjistit, kolik z těchto prvočísel působit jako dělitel (a jak často).

Zde je několik python pro algo Podívejte se zde a hledejte „Předmět: matematika - nutnost dělitelů algoritmus“. Jen spočítat počet položek v seznamu namísto jejich vracení nicméně.

Tady je Dr. Math , který vysvětluje, co přesně to je, co musíte udělat matematicky.

V podstatě se scvrkává na, pokud vaše číslo nje:
n = a^x * b^y * c^z
(kde a, b, a c jsou n premiér dělitele a x, y a z jsou kolikrát, že dělitel je opakované), pak celkový počet pro všechny dělitelů je:
(x + 1) * (y + 1) * (z + 1),

Edit: BTW, najít, B, C, atd budete chtít dělat to, co činí chamtivý algo, jestli jsem to pochopit správně. Začněte u své největší primární dělitel a množte se, že samo o sobě až do dalšího množení by překročil číslo n. Pak se přesuňte na další nejnižším koeficientem a časy předchozí primární ^ kolikrát to bylo vynásobený aktuální připravit a udržet vynásobením rozkvětu až do příštího překročí n ... atd. Mějte přehled o tom, kolikrát budete násobit dělitele dohromady a použít tato čísla do výše uvedeného vzorce.

Není 100% jistý mé Algo popisu, ale pokud tomu tak není, že je to něco podobného.

Odpovězeno 21/09/2008 v 07:03
zdroj uživatelem

hlasů
-1

Nevím, co nejefektivnější způsob, ale já bych to takto:

  • Vytvořit tabulku prvočísel najít všechny připraví méně než nebo rovnou druhé odmocnině z počtu (Osobně bych použít síto Atkin)
  • Spočítat všechny připraví méně než nebo rovnou druhé odmocnině počtu a násobit, že dva. V případě, že druhá odmocnina z počtu, je celé číslo, pak odečíst jeden od proměnné Count.

Měl by fungovat \ o /

Pokud budete potřebovat, mohu kódu něco zítra v C na demonstraci.

Odpovězeno 21/09/2008 v 07:16
zdroj uživatelem

hlasů
5

Síto Atkin je optimalizovaná verze eratosthenovo síto, která dává všem prvočísel až do dané číslo. Měli byste být schopni google to pro další podrobnosti.

Jakmile máte tento seznam, je to jednoduchá záležitost rozdělit své číslo každým prime aby zjistil, jestli je to přesně dělitel (tj zbytek je nula).

Základní kroky výpočtu dělitele pro množství (n) jsou [to je pseudokód převeden ze skutečného kódu, takže doufám, že nezavedly chyby]:

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
Odpovězeno 21/09/2008 v 07:36
zdroj uživatelem

hlasů
46

Existuje mnoho dalších technik k faktoringu, než sítem Atkin. Dejme tomu, že chceme, aby faktor 5893. No jeho sqrt je 76,76 ... Teď se budeme snažit psát 5893 jako součin čtverce. No (77 * 77 - 5893) = 36, což je 6 na druhou, takže 5893 = 77 * 77-6 * 6 = (77 + 6) (77-6) = 83 * 71. Pokud to nefungovalo bychom se dívali na to, zda 78 * 78 - 5893 byl dokonalý čtverec. A tak dále. S touto technikou můžete rychle testovat faktory blízko k druhé odmocnině n mnohem rychleji, než by testování jednotlivých prvočísla. Spojíte-li tuto techniku pro vyloučil velký připraví se sítem, budete mít mnohem lepší způsob factoringové než samotným sítem.

A to je jen jedna z velkého množství technik, které byly vyvinuty. Jedná se o poměrně jednoduchý. Bylo by trvat dlouho, než se učit, řekněme dost teorie čísel pochopit factoringových techniky založené na eliptických křivek. (Já vím, že existují. Nerozumím jim.)

Proto, pokud máte co do činění s malými celými čísly, tak bych se snažit vyřešit tento problém sám. Místo toho jsem se snaží najít způsob, jak používat něco jako PARI knihovny, která již má vysoce efektivní řešení implementované. S tím mohu faktor náhodné 40 místné číslo jako 124321342332143213122323434312213424231341 asi za 0,05 sekundy. (Jeho faktorizace, v případě, že jste přemýšlel, je 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949 . Jsem si docela jistý, že to nemělo přijít na to s použitím síta z Atkin ...)

Odpovězeno 21/09/2008 v 09:47
zdroj uživatelem

hlasů
9

Odpověď na vaši otázku do značné míry závisí na velikosti celé číslo. Metody pro malé množství, například méně než 100 bitů, a čísla ~ 1000 bitů (například, jak je používán v kryptografii), jsou zcela odlišné.

Odpovězeno 21/09/2008 v 19:38
zdroj uživatelem

hlasů
27

Nesouhlasím, že síto Atkin je způsob, jak jít, protože by to mohlo snadno trvat déle, kontrolovat každé číslo v [1, n] pro primality než by ke snížení počtu by divizí.

Zde je několik kód, který, i když mírně hackier, je obecně mnohem rychlejší:

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 To funguje Python kód k řešení tohoto problému.

Odpovězeno 23/09/2008 v 02:53
zdroj uživatelem

hlasů
10

Tato zajímavá otázka je mnohem těžší, než se zdá, a to nebyla zodpovězena. Otázkou může být zapracovány do 2 velmi různé otázky.

1. vzhledem k tomu, N, najít seznam litrů prvočinitele n '

2 vzhledem k tomu, L, vypočítat počet jedinečných kombinací

Všechny odpovědi vidím tak daleko odkazují na # 1 a nezmínit nejde povolný pro obrovských množstvích. Pro středně velké N i 64-bitových čísel, je snadné; k obrovskému N, problém factoring může mít „na věčné časy“. Šifrování s veřejným klíčem závisí na toto téma.

Otázka # 2 potřebuje další diskusi. Pokud L obsahuje pouze jedinečné číslo, jedná se o jednoduchý výpočet s použitím kombinace vzorec pro výběr k objektů z n bodů. Ve skutečnosti, je třeba shrnout výsledky z použití vzorce, když se mění k, od 1 do sizeof (L). Nicméně, L obvykle obsahuje více výskytů více připraví. Například, L = {2,2,2,3,3,5} je faktorizace N = 360. Nyní tento problém je poměrně obtížné!

Přeformulování # 2, vzhledem k tomu, kolekce C obsahující K předměty, jako je tato položka A má "duplikáty, a bod b má B- duplicity, atd. Kolik unikátních kombinací 1 do K-1 položky jsou k dispozici? Například, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} musí každý nastat jednou a pouze jednou, pokud L = {2,2 , 2,3,3,5}. Každý takový jedinečný dílčí kolekce je unikátní dělitelem N vynásobením položky v sub-sbírky.

Odpovězeno 04/11/2008 v 03:52
zdroj uživatelem

hlasů
5

Můžete zkusit tohle. Je to trochu hackish, ale je to poměrně rychle.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
Odpovězeno 18/07/2009 v 04:31
zdroj uživatelem

hlasů
3

Předtím, než se zavázat k roztoku se domnívají, že tento přístup Sieve nemusí být dobrá odpověď v typickém případě.

Před nějakou dobou došlo k prime otázka a já test času - na 32-bitová celá čísla alespoň určují, jestli je to prime byl pomalejší než hrubá síla. Existují dva faktory děje:

1) I když člověk chvíli trvá, než dělat divize jsou velmi rychlé na počítači - podobně jako náklady na vyhledávání odpověď.

2) V případě, že nemáte nejlepší tabulku můžete vytvořit smyčku, která běží úplně v L1 cache. To vám umožní rychleji.

Odpovězeno 18/07/2009 v 05:11
zdroj uživatelem

hlasů
5

Jakmile budete mít primární faktorizaci, existuje způsob, jak zjistit počet dělitelů. Přidejte jeden ke každému z exponentů na každém jednotlivém faktoru a pak násobit exponenty dohromady.

Například: 36 primární faktorizace: 2 ^ 2 * 3 ^ 2 dělitele: 1, 2, 3, 4, 6, 9, 12, 18, 36 Počet dělitele: 9

Přidejte jeden pro každý exponent 2 ^ 3 * 3 ^ 3 Násobení exponenty: 3 * 3 = 9

Odpovězeno 02/02/2010 v 01:28
zdroj uživatelem

hlasů
2

Dělitele udělat něco velkolepého: rozdělují úplně. Chcete-li zjistit počet dělitele na řadě, nto je samozřejmě zbytečné rozpětí celé spektrum, 1...n. Neudělal jsem žádný výzkum do hloubky za to ale vyřešil jsem Project Eulerovu problém 12 na trojúhelníkových čísel . Mé řešení pro větší než 500 dělitele testu běžel 309504 mikrosekund (~ 0.3s). Napsal jsem tuto funkci dělitel k řešení.

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

Ke každému algoritmu, je slabinou. Myslel jsem, že to byl slabý proti prvočísel. Ale protože trojúhelníková čísla nejsou tisku, že splnila svůj účel bezchybně. Z mého profilování, myslím, že to udělal velmi dobře.

Šťastné svátky.

Odpovězeno 30/12/2010 v 22:19
zdroj uživatelem

hlasů
33

@Yasky

Vaše funkce dělitele má chybu v tom, že nefunguje správně pro dokonalé čtverce.

Snaž se:

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;
}
Odpovězeno 23/03/2011 v 15:32
zdroj uživatelem

hlasů
6

Jen jeden řádek
jsem si myslel, že velmi pečlivě o své otázky a já jsem se snažil psát vysoce efektivní a výkonný kus kódu Chcete-li vytisknout všechny dělitele daného čísla na obrazovce, které potřebujeme pouze jeden řádek kódu! (možnost využití -std = C99 při kompilaci pomocí 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

Pro zjištění počtu dělitelů můžete použít následující velice rychlý funkci (správně fungovat pro všechny celé číslo s výjimkou 1 a 2)

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

nebo pokud se chováte uveden počet jako dělitel (správně fungovat pro všechny celé číslo s výjimkou 1 a 2)

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

Poznámka: dvě výše uvedené funkce pracuje správně pro všechny kladné celé číslo kromě čísla 1 a 2, takže to bude fungovat pro všechna čísla, která jsou větší než 2, avšak pokud budete potřebovat na pokrytí 1 a 2, můžete použít jednu z následujících funkcí (poněkud pomalejší)

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

NEBO

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

malé, to je krásné :)

Odpovězeno 11/11/2011 v 03:59
zdroj uživatelem

hlasů
1

primární způsob číslo je zde velmi jasné. P [] je uveden seznam prvočíslo menší než nebo rovnou 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  .
Odpovězeno 10/01/2013 v 00:12
zdroj uživatelem

hlasů
8

Zde je přímočará O (sqrt (n)) algoritmus. Použil jsem to řešit 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  
Odpovězeno 05/04/2013 v 05:32
zdroj uživatelem

hlasů
1

teorie čísel učebnice volání funkce dělitel-počítání tau. První Zajímavým faktem je, že je multiplikativní, tzn. τ (ab) = τ (a) τ (b), kde A a B mají žádný společný faktor. (Důkaz: každá dvojice dělitele a a b poskytuje zřetelný dělitele ab).

Právě vědomí, že u pa prvočíslo, ▼ (p ** k) = k + 1 (pravomocí p). Takto můžete snadno spočítat ▼ můžete (n) z jeho faktorizace.

Nicméně factorising velké množství může být pomalé (bezpečnost RSA crytopraphy závisí na součin dvou velkých prvočísel bytí těžké factorise). To naznačuje tento optimalizovaný algoritmus

  1. Test, zda je číslo prvočíslo (rychle)
  2. Pokud ano, vrátí 2
  3. V opačném případě factorise číslo (pomalé, pokud několika velkých prvočinitele)
  4. Vypočtěte ▼ se (n) z faktorizace
Odpovězeno 14/07/2013 v 13:15
zdroj uživatelem

hlasů
1

Níže je C program najít počet dělitele daného čísla.

Složitost výše uvedeného algoritmu je O (sqrt (n)).

Tento algoritmus bude pracovat správně číslo, které mají dokonalý čtverec, jakož i čísla, která nejsou dokonalý čtverec.

Všimněte si, že UPPERLIMIT smyčky je nastavena na druhé odmocnině počtu mít algoritmus nejefektivnější.

Všimněte si, že ukládání UPPERLIMIT v samostatném proměnné také šetří čas, neměli byste zavolat funkci sqrt v sekci stavu pro smyčce, to také šetří výpočetní čas.

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

Namísto výše smyčky, můžete také použít následující smyčku, která je ještě účinnější, protože to odstraňuje potřebu najít druhé odmocnině počtu.

for(i=2;i*i<=n;i++)
{
    ...
}
Odpovězeno 19/08/2014 v 14:35
zdroj uživatelem

hlasů
1

Zde je funkce, která jsem napsal. je to nejhorší časová složitost je O (sqrt (n)), nejlepší čas na druhé straně je O (log (n)). To vám dává všechny primární dělitele spolu s číslem jeho výskytu.

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;
}
Odpovězeno 01/12/2014 v 13:02
zdroj uživatelem

hlasů
3

Jedná se o efektivní řešení:

#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;
}
Odpovězeno 01/12/2014 v 14:01
zdroj uživatelem

hlasů
1

To je nejzákladnější způsob výpočtu číselných 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);

    }
}
Odpovězeno 02/12/2014 v 03:25
zdroj uživatelem

hlasů
0

To je něco, co jsem přišel s založené na Justin odpověď. To by mohlo vyžadovat určitou optimalizaci.

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))
Odpovězeno 29/11/2015 v 07:30
zdroj uživatelem

hlasů
0

Myslím, že to je to, co hledáte for.I dělá přesně to, co chtěl. Zkopírovat a vložit jej do Notepad.Save as * .bat.Run.Enter Number.Multiply proces 2 a to je počet divisors.I udělal schválně, takže to určit dělitele rychleji:

Pls na vědomí, že CMD varriable převýšení hodnoty podpory přes 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
Odpovězeno 07/02/2016 v 21:24
zdroj uživatelem

hlasů
1

@Kendall

Testoval jsem svůj kód a provedla několik vylepšení, nyní je to ještě rychlejší. Také jsem testoval s @ هومن جاویدپور kódu, to je také rychlejší než jeho kódu.

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;
}
Odpovězeno 11/11/2016 v 15:32
zdroj uživatelem

hlasů
0

Myslím, že tohle bude hodit, stejně jako přesné

script.pyton

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

Odpovězeno 23/01/2017 v 15:57
zdroj uživatelem

hlasů
0

Zkuste něco v tomto smyslu:

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;
}
Odpovězeno 23/01/2017 v 16:01
zdroj uživatelem

hlasů
0

Můžete precompute prvočísla až do řadové kořene maximální možnou N a počítat exponent každé prvočíslo řady. Počet dělitelů n (n = p1 ^ a p2 ^ b P3 ^ C ...) je (a + 1) (b + 1) (c + 1), protože je to stejné, jako počítat způsob kombinovat nultý počty těchto faktorů (a to bude počítat počet dělitelů). Je to velmi rychle, pokud precompute prvočísla

Podrobnější informace o této metodě:

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;
    }
}
Odpovězeno 17/12/2017 v 15:40
zdroj uživatelem

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