Algorithme pour calculer le nombre de diviseurs d'un nombre donné

voix
163

Quel serait l'algorithme le plus optimal (en terme de performance) pour calculer le nombre de diviseurs d'un nombre donné?

Ça va être génial si vous pouvez fournir ou pseudocode un lien vers quelques exemples.

EDIT: Toutes les réponses ont été très utiles, je vous remercie. Je mise en œuvre du Crible d'Atkin et je vais utiliser quelque chose de semblable à ce qui a indiqué Jonathan Leffler. Le lien posté par Justin Bozonier a plus d'informations sur ce que je voulais.

Créé 21/09/2008 à 06:44
source utilisateur
Dans d'autres langues...                            


28 réponses

voix
1

Vous voulez que le Crible d'Atkin, décrit ici: http://en.wikipedia.org/wiki/Sieve_of_Atkin

Créé 21/09/2008 à 06:53
source utilisateur

voix
0

Est-ce pas juste une question d'affacturage du nombre - la détermination de tous les facteurs du nombre? Vous pouvez alors décider si vous avez besoin de toutes les combinaisons d'un ou plusieurs facteurs.

Ainsi, un algorithme possible serait la suivante:

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

Il est alors à vous de combiner les facteurs pour déterminer le reste de la réponse.

Créé 21/09/2008 à 06:59
source utilisateur

voix
74

Dmitriy est juste que vous voulez que le Crible d'Atkin pour générer la liste mais je ne premier crois pas que se charge de toute la question. Maintenant que vous avez une liste de nombres premiers, vous aurez besoin de voir combien de ces nombres premiers agissent comme un diviseur (et à quelle fréquence).

Voici quelques python pour la algo Regardez ici et recherchez « Objet: mathématiques - besoin algorithme de diviseurs ». Il suffitcompter le nombre d'éléments dans la listelieu de les renvoyer cependant.

Voici un Dr Math qui explique exactement ce que vous devez faire mathématiquement.

Essentiellement , cela se résume à si votre numéro nest:
n = a^x * b^y * c^z
(a, b, et c sont des diviseurs premiers et x de n, y et z sont le nombre de fois que le diviseur est répété), le nombre total pour tous les diviseurs est:
(x + 1) * (y + 1) * (z + 1).

Edit: BTW, trouver a, b, c, etc, vous aurez envie de faire ce qui équivaut à un algo gourmand si je comprends cela correctement. Commencez par votre plus grand diviseur premier et le multiplier par lui-même jusqu'à ce qu'une nouvelle multiplication dépasserait le nombre n. Passez ensuite à l'autre facteur le plus bas et le premier temps précédent ^ nombre de fois qu'il a été multiplié par le premier courant et continuer à multiplier par le premier jusqu'à ce que le prochain dépassera n ... etc. Gardez une trace du nombre de fois que vous multipliez le ensemble et appliquent diviseurs ces nombres dans la formule ci-dessus.

Pas sûr à 100% ma description algo mais si ce n'est pas ce qu'il est quelque chose de similaire.

Créé 21/09/2008 à 07:03
source utilisateur

voix
-1

Je ne connais pas la méthode la plus efficace, mais je fais ce qui suit:

  • Créer une table de nombres premiers pour trouver tous les nombres premiers inférieur ou égal à la racine carrée du nombre (Personnellement, j'utiliser le Crible d'Atkin)
  • Compte de tous les nombres premiers inférieur ou égal à la racine carrée du nombre et de multiplier par deux. Si la racine carrée du nombre est un nombre entier, puis soustraire un de la variable de comptage.

Si le travail \ o /

Si vous avez besoin, je peux coder quelque chose demain en C pour démontrer.

Créé 21/09/2008 à 07:16
source utilisateur

voix
5

Le tamis de Atkin est une version optimisée du tamis d'Eratosthène qui donne tous les nombres premiers pour un entier donné. Vous devriez être en mesure de google pour plus de détails.

Une fois que vous avez cette liste, il est une simple question de diviser votre numéro par chaque prime pour voir si elle est un diviseur exact (c.-à, le reste est égal à zéro).

Les étapes de base de calcul des diviseurs pour un certain nombre (n) sont [c'est converti à partir du code pseudo-code réel donc j'espère que je ne l'ai pas les erreurs introduites]:

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
Créé 21/09/2008 à 07:36
source utilisateur

voix
46

Il y a beaucoup plus de techniques à l' affacturage que le tamis de Atkin. Par exemple , supposons que nous voulons tenir compte 5893. Eh bien son sqrt est 76,76 ... Maintenant , nous allons essayer d'écrire 5893 en tant que produit de carrés. Bien (77 * 77-5893) = 36 qui est 6 au carré, de sorte que 5893 = 77 * 77-6 * 6 = (77 + 6) (77-6) = 83 * 71. Si cela n'avait pas travaillé , nous aurions cherché à savoir si 78 * 78-5893 était un carré parfait. Etc. Avec cette technique , vous pouvez tester rapidement des facteurs près de la racine carrée de n beaucoup plus rapide que par des tests individuels des nombres premiers. Si vous combinez cette technique pour écarter les grands nombres premiers avec un tamis, vous aurez une bien meilleure méthode d'affacturage qu'avec le tamis seul.

Et cela est juste un d'un grand nombre de techniques qui ont été développées. Ceci est assez simple. Il vous faudra beaucoup de temps pour apprendre, par exemple, la théorie des nombres assez pour comprendre les techniques d'affacturage basées sur les courbes elliptiques. (Je sais qu'ils existent. Je ne les comprends pas.)

Par conséquent , à moins que vous traitez avec des petits entiers, je ne voudrais pas essayer de résoudre ce problème moi - même. Au lieu de cela , je vais essayer de trouver un moyen d'utiliser quelque chose comme le PARI bibliothèque qui a déjà une solution très efficace mis en œuvre. Avec ce que je peux tenir un nombre de 40 chiffres au hasard comme 124321342332143213122323434312213424231341 dans environ 0,05 secondes. (Son factorisation, au cas où vous me demandais, est de 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949. Je suis tout à fait convaincu qu'il ne figure pas à l' aide de ce tamis de Atkin ...)

Créé 21/09/2008 à 09:47
source utilisateur

voix
9

Une réponse à votre question dépend en grande partie de la taille de l'entier. Méthodes pour un petit nombre, par exemple moins de 100 bits, et pour les nombres ~ 1000 bits (tels que ceux utilisés dans la cryptographie) sont complètement différents.

Créé 21/09/2008 à 19:38
source utilisateur

voix
27

Je suis en désaccord que le tamis de Atkin est le chemin à parcourir, car il pourrait facilement prendre plus de temps pour vérifier chaque numéro [1, n] pour primalité que ce serait de réduire le nombre de divisions.

Voici un code qui, bien que légèrement hackier, est généralement beaucoup plus rapide:

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 qui travaille code Python pour résoudre ce problème.

Créé 23/09/2008 à 02:53
source utilisateur

voix
10

Cette question intéressante est beaucoup plus difficile qu'il n'y paraît, et il n'a pas été répondu. La question peut être pris en 2 questions très différentes.

1 N donné, trouver la liste L des facteurs premiers de N

2 L donnée, calculer le nombre de combinaisons uniques

Toutes les réponses que je vois si loin se réfèrent à 1 et ne parviennent pas à le mentionner ne sont pas traitables pour les nombres énormes. Pour de taille moyenne N, même nombre 64 bits, il est facile; pour énorme N, le problème d'affacturage peut prendre « pour toujours ». chiffrement à clé publique dépend.

Question n ° 2 a besoin de plus de discussion. Si L ne contient que des numéros uniques, il est un calcul simple en utilisant la formule de combinaison pour le choix des objets k de n éléments. En fait, vous devez résumer les résultats de l'application de la formule en faisant varier k de 1 à sizeof (L). Cependant, L contient généralement plusieurs occurrences de plusieurs nombres premiers. Par exemple, L = {2,2,2,3,3,5} est la factorisation de N = Maintenant, ce problème 360. est assez difficile!

Reformulant # 2, compte tenu de la collection C contenant des éléments de k, de telle sorte qu'un objet a un doublon, et le point b a b 'doublons, etc. combien de combinaisons uniques de 1 à k-1 éléments sont là? Par exemple, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} doit se produire chaque fois et une fois seulement si L = {2,2 , 2,3,3,5}. Chacun de ces sous-collection unique est un diviseur unique de N en multipliant les éléments de la sous-collection.

Créé 04/11/2008 à 03:52
source utilisateur

voix
5

Vous pouvez essayer celui-ci. Il est un peu hackish, mais il est assez rapide.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
Créé 18/07/2009 à 04:31
source utilisateur

voix
3

Avant de vous engager à une solution considérer que l'approche Sieve pourrait ne pas être une bonne réponse dans le cas typique.

Un certain temps il y avait une question de choix et je l'ai fait un test de temps - pour les entiers 32 bits au moins de déterminer si elle était premier était plus lent que la force brute. Il y a deux facteurs en cours:

1) Alors qu'un homme prend un certain temps pour faire une division, ils sont très rapides sur l'ordinateur - similaire au coût de la réponse à la recherche.

2) Si vous ne disposez pas d'une table de choix que vous pouvez faire une boucle qui fonctionne entièrement dans le cache L1. Cela le rend plus rapide.

Créé 18/07/2009 à 05:11
source utilisateur

voix
5

Une fois que vous avez la factorisation, il y a un moyen de trouver le nombre de diviseurs. Ajouter une à chacun des exposants sur chaque facteur individuel, puis multiplier les exposants ensemble.

Par exemple: 36 Premier factorisation: 2 ^ 2 * 3 ^ 2 diviseurs: 1, 2, 3, 4, 6, 9, 12, 18, 36 nombre de diviseurs: 9

Ajouter un à chaque exposant 2 ^ 3 * 3 ^ 3 exposants Multiplier: 3 * 3 = 9

Créé 02/02/2010 à 01:28
source utilisateur

voix
2

Divisors font quelque chose de spectaculaire: ils se divisent complètement. Si vous voulez vérifier le nombre de diviseurs pour un certain nombre, nil est clairement redondant pour couvrir tout le spectre, 1...n. Je ne l' ai pas fait de recherches approfondies pour cela , mais je résolu le problème du projet Euler 12 sur les Nombres Triangulaires . Ma solution pour le plus de500 diviseurs essai couru pour 309504 microsecondes (~ 0,3s). J'ai écrit cette fonction de diviseur pour la solution.

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

Pour chaque algorithme, il y a un point faible. Je pensais que c'était faible par rapport à des nombres premiers. Mais puisque les nombres triangulaires ne sont pas imprimer, il a atteint son but sans faille. De mon profil, je pense qu'il a fait assez bien.

Joyeuses fêtes.

Créé 30/12/2010 à 22:19
source utilisateur

voix
33

@Yasky

Votre fonction a un bug diviseurs en ce qu'il ne fonctionne pas correctement pour des carrés parfaits.

Essayer:

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;
}
Créé 23/03/2011 à 15:32
source utilisateur

voix
6

Juste une ligne
que j'ai pensé très précieusement à votre question et j'ai essayé d'écrire un morceau de code très efficace et performant Pour imprimer tous les diviseurs d'un nombre donné à l' écran , nous avons juste besoin d' une ligne de code! (option = utilisation -STD C99 lors de la compilation 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

pour trouver le nombre de diviseurs vous pouvez utiliser la fonction suivante très très rapide (travail correctement pour tout nombre entier sauf 1 et 2)

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

ou si vous traitez nombre donné comme un diviseur (travail correctement pour tout nombre entier sauf 1 et 2)

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

REMARQUE: deux fonctions ci-dessus fonctionne correctement pour tout nombre entier positif, sauf le numéro 1 et 2 il est donc fonctionnel pour tous les chiffres qui sont supérieurs à 2, mais si vous avez besoin pour couvrir 1 et 2, vous pouvez utiliser l'une des fonctions suivantes (un peu Ralentissez)

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

OU

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

petit est beau :)

Créé 11/11/2011 à 03:59
source utilisateur

voix
1

la méthode des nombres premiers est très clair. P [] est une liste de nombres premiers inférieur ou égal au carré = 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  .
Créé 10/01/2013 à 00:12
source utilisateur

voix
8

Voici un algorithme avant O droite (sqrt (n)). J'ai utilisé pour résoudre ce projet 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  
Créé 05/04/2013 à 05:32
source utilisateur

voix
1

manuels théorie des nombres appellent la protéine tau fonction diviseur de comptage. Le premier fait intéressant est que c'est multiplicatif, par exemple. τ (ab) = τ (a) τ (b), lorsque A et B ont pas de facteur commun. (Preuve: chaque paire de diviseurs de a et b donne un diviseur distinct de ab).

noter maintenant que pour le premier pa, τ (p ** k) = k + 1 (les puissances de p). Ainsi, vous pouvez facilement calculer τ (n) de son factorisation.

Cependant factoriser un grand nombre peuvent être lents (la sécurité de RSA crytopraphy dépend du produit de deux grands nombres premiers étant difficile à factoriser). Cela suggère cet algorithme optimisé

  1. Test si le nombre est premier (rapide)
  2. Si oui, retour 2
  3. Dans le cas contraire, factoriser le nombre (lent si plusieurs grands facteurs premiers)
  4. Calculer τ (n) à partir de la factorisation
Créé 14/07/2013 à 13:15
source utilisateur

voix
1

Ce qui suit est un programme C pour trouver le nombre de diviseurs d'un nombre donné.

La complexité de l'algorithme ci-dessus est O (sqrt (n)).

Cet algorithme fonctionne correctement pour le nombre qui sont carré parfait ainsi que les chiffres qui ne sont pas carré parfait.

Notez que le UpperLimit de la boucle est définie sur la racine carrée du nombre d'avoir l'algorithme le plus efficace.

Notez que le stockage de la UpperLimit dans une variable séparée permet aussi d'économiser le temps, vous ne devriez pas appeler la fonction sqrt dans la section de l'état de la boucle, cela permet d'économiser aussi votre temps de calcul.

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

Au lieu de ce qui précède pour la boucle, vous pouvez également utiliser la boucle suivante qui est encore plus efficace car cela élimine la nécessité de trouver la racine carrée du nombre.

for(i=2;i*i<=n;i++)
{
    ...
}
Créé 19/08/2014 à 14:35
source utilisateur

voix
1

Voici une fonction que je l'ai écrit. il est pire complexité est en O (sqrt (n)), le meilleur temps d'autre part est O (log (n)). Il vous donne tous les diviseurs premiers ainsi que le nombre de ses SURVENANCE.

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;
}
Créé 01/12/2014 à 13:02
source utilisateur

voix
3

Ceci est une solution efficace:

#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;
}
Créé 01/12/2014 à 14:01
source utilisateur

voix
1

Ceci est la façon la plus simple de calculer le nombre 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);

    }
}
Créé 02/12/2014 à 03:25
source utilisateur

voix
0

Ceci est quelque chose que je suis venu avec fonction de la réponse Justin. Il pourrait nécessiter une optimisation.

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))
Créé 29/11/2015 à 07:30
source utilisateur

voix
0

Je pense que c'est ce que vous cherchez for.I fait exactement ce que vous avez demandé. Copier et coller dans Notepad.Save comme * .bat.Run.Enter Number.Multiply le processus par 2 et thats le nombre de divisors.I fait que exprès pour le déterminer, il les diviseurs plus vite:

Pls noter qu'un CMD varriable valeurs de support catifs sur 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
Créé 07/02/2016 à 21:24
source utilisateur

voix
1

@Kendall

Je l'ai testé votre code et apporté quelques améliorations, maintenant il est encore plus rapide. J'ai aussi testé avec @ هومن جاویدپور code, c'est aussi plus rapide que son 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;
}
Créé 11/11/2016 à 15:32
source utilisateur

voix
0

Je suppose que celui-ci sera à portée de main, ainsi que précis

script.pyton

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

Créé 23/01/2017 à 15:57
source utilisateur

voix
0

Essayez quelque chose le long de ces lignes:

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;
}
Créé 23/01/2017 à 16:01
source utilisateur

voix
0

Vous pouvez précalculer les nombres premiers jusqu'à la racine de sqaure du possible N max et calculer l'exposant de chaque facteur premier d'un nombre. Le nombre de diviseurs de n (n = p1 ^ p2 ^ b ^ p3 c ...) est (a + 1) (b + 1) (c + 1), car il est le même que la façon de compter combiner le premier nombre de ces facteurs (et cela comptera le nombre de diviseurs). Ceci est très rapide si vous Précalculer les nombres premiers

informations plus détaillées sur cette méthode:

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;
    }
}
Créé 17/12/2017 à 15:40
source utilisateur

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