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


177

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

Ce serait formidable si vous pouviez fournir un pseudocode ou un lien vers un exemple.

EDIT: Toutes les réponses ont été très utiles, merci. J'implémente le tamis d'Atkin et ensuite je vais utiliser quelque chose de similaire à ce que Jonathan Leffler a indiqué. Le lien posté par Justin Bozonier a de plus amples informations sur ce que je voulais.


Compte tenu de vos demandes, le nombre de facteurs est vague. Je suppose que vous recherchez le nombre de diviseurs premiers non uniques, car si vous ne voulez pas que je code, écrivez simplement un programme pour toujours retourner 1 si le nombre à factoriser est un et 2 si c'est autre chose. 0 pourrait avoir besoin d'un changement ...
Justin Bozonier

@sker: existe-t-il une plage de valeurs pour laquelle vous avez besoin des diviseurs. Il existe de nombreuses façons de calculer les facteurs, et chaque méthode est mieux adaptée à une plage particulière.
Ande Turner

2
Voici un problème intéressant lié projecteuler.net/problem=12
daniloquio

1
Le tamis naïf d'Atkin, même de l'article Wikipédia édité, ne sera jamais plus rapide qu'un tamis d'Eratosthène factorisé au maximum par roue jusqu'à d'énormes limites irréalisables, et les versions segmentées par page sont encore plus en faveur du SoE (voir SoE primesieve versus SoA primegen as mis en œuvre par Bernstein, le partenaire d'Atkin. Il est courant de savoir que leur étude a prouvé SoA plus rapidement, mais ils ont artificiellement limité l'optimisation du SoE utilisé pour le prouver. Voir ma réponse SoA pour plus d'explications
GordonBGood

Réponses:


78

Dmitriy a raison de dire que vous voudrez que le tamis d'Atkin génère la liste principale, mais je ne pense pas que cela règle tout le problème. Maintenant que vous avez une liste de nombres premiers, vous devrez voir combien de ces nombres premiers agissent comme un diviseur (et à quelle fréquence).

Voici quelques python pour l'algo Regardez ici et recherchez "Subject: math - need divisors algorithm". Comptez simplement le nombre d'articles dans la liste au lieu de les renvoyer.

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

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

Edit: BTW, pour trouver a, b, c, etc., vous voudrez faire ce qui équivaut à un algo gourmand si je comprends bien cela. Commencez par votre plus grand diviseur premier et multipliez-le par lui-même jusqu'à ce qu'une autre multiplication dépasse le nombre n. Ensuite, passez au facteur le plus bas suivant et multipliez le nombre premier ^ précédent de fois qu'il a été multiplié par le premier courant et continuez à multiplier par le premier jusqu'à ce que le suivant dépasse n ... etc. Gardez une trace du nombre de fois que vous multipliez le diviseurs ensemble et appliquez ces nombres dans la formule ci-dessus.

Je ne suis pas sûr à 100% de ma description d'algo, mais si ce n'est pas le cas, c'est quelque chose de similaire.


1
Si vous factorisez un grand nombre, vous ne voulez même pas avoir à regarder la liste principale. Vous voulez éliminer au plus vite toute une gamme de possibilités! Voir ma réponse pour plus.
user11318

Je me rends compte que c'était il y a 2 ans, mais votre lien python algo est rompu, vous savez où il existe maintenant?
jb.

2
Ainsi n = (a^x * b^y * c^z)-(x + 1) * (y + 1) * (z + 1)est la règle
SIslam

1
Comme le dit @Shashank, l'algorithme de la section "EDIT:" est faux: supposons que n = 45 = 3 * 3 * 5. Le plus grand diviseur premier est 5, mais le multiplier par lui-même jusqu'à ce qu'il dépasse n amènerait l'algorithme à signaler qu'il a 2 copies du facteur 5 (puisque 5 * 5 = 25 <45).
j_random_hacker

1
Le 'Sieve of Atkin' a une complexité d'exécution de O (N / log (log (N))) au mieux. La vérification par force brute de tous les diviseurs possibles de 1 ... Sqrt (n) a une complexité d'exécution de O (Sqrt (N)) qui est bien supérieure. Comment se fait-il que cette réponse ait été acceptée?
le_m

47

Il y a beaucoup plus de techniques d'affacturage que le tamis d'Atkin. Par exemple, supposons que nous voulons factoriser 5893. Eh bien, son sqrt est 76,76 ... Nous allons maintenant essayer d'écrire 5893 comme un produit de carrés. Eh bien (77 * 77 - 5893) = 36 qui est 6 au carré, donc 5893 = 77 * 77 - 6 * 6 = (77 + 6) (77-6) = 83 * 71. Si cela n'avait pas fonctionné, nous aurions vérifié si 78 * 78 - 5893 était un carré parfait. Etc. Avec cette technique, vous pouvez tester rapidement les facteurs proches de la racine carrée de n beaucoup plus rapidement qu'en testant des nombres premiers individuels. Si vous combinez cette technique pour éliminer les grands nombres premiers avec un tamis, vous aurez une bien meilleure méthode d'affacturage qu'avec le tamis seul.

Et ce n'est qu'une des nombreuses techniques qui ont été développées. C'est une question assez simple. Il vous faudrait beaucoup de temps pour apprendre, disons, suffisamment de théorie des nombres 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 n'ayez affaire à de petits nombres entiers, je n'essaierai pas de résoudre ce problème moi-même. Au lieu de cela, j'essaierais de trouver un moyen d'utiliser quelque chose comme la bibliothèque PARI qui a déjà mis en œuvre une solution très efficace. Avec cela, je peux factoriser un nombre aléatoire de 40 chiffres comme 124321342332143213122323434312213424231341 en environ 0,05 seconde. (Sa factorisation, au cas où vous vous poseriez la question, est de 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949. Je suis convaincu qu'il n'a pas compris cela en utilisant le tamis d'Atkin ...)


1
Votre technique est très intelligente, mais elle ne me dit pas combien de facteurs le nombre a-t-il, n'est-ce pas?
sker le

23
Une fois que vous avez la factorisation principale, déterminer le nombre de facteurs est simple. Supposons que les facteurs premiers soient p1, p2, ..., pk et qu'ils soient répétés m1, m2, ..., mk fois. Ensuite, il y a (1 + m1) (1 + m2) ... (1 + mk) facteurs.
user11318

Un tamis intéressant est le tamis quadratique . Cela utilise la théorie des nombres - congruences quadratiques et une certaine algèbre linéaire. J'ai suffisamment appris pour l'utiliser dans un cours de théorie des nombres de 2e année à l'université.
Tanner

33

@Yasky

Votre fonction de diviseurs a un bogue en ce sens qu'elle ne fonctionne pas correctement pour les 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;
}

6
(X% i) ne causera-t-il pas une division par zéro lorsque i = 0? devrais-je = 1..limit?
rhu

@rhu Vérifier 0 est de toute façon inutile car 0 n'est pas un facteur d'un nombre quelconque.
EJoshuaS - Réintégrer Monica le

29

Je ne suis pas d'accord pour dire que le tamis d'Atkin est la voie à suivre, car il pourrait facilement prendre plus de temps pour vérifier chaque nombre de [1, n] pour la primalité que pour réduire le nombre par divisions.

Voici un code qui, bien que légèrement plus piraté, 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 C'est du code python qui fonctionne pour résoudre ce problème.


11

Voici un algorithme O (sqrt (n)) simple. J'ai utilisé ceci pour résoudre le 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
    if i ** 2 == n:
        count += 1
    return count

mais pourquoi augmentez-vous toujours le nombre de 2? ... y a-t-il un théorème que vous avez appliqué?
SummerCode

3
parce que vous n'êtes contingent que jusqu'à sqrt (n). Par exemple: si vous essayez de trouver tous les diviseurs pour 36 - vous compterez de 2 à 6. Vous savez que 1 & 36,2 & 18, 3 & 12, 4 & 9, 6,6 sont tous des diviseurs et ils viennent par paires.
Antony Thomas

2
merci beaucoup Anthony, j'ai compris maintenant: D! un petit addendum: je pense qu'il devrait traiter la valeur sqrt (n) séparément car pour l'instant il le prend en considération deux fois au lieu d'une, je pense
SummerCode

Alors que O (sqrt (n)) n'est pas trop mauvais, ce n'est pas optimal. le calcul de la décomposition des facteurs premiers peut être effectué beaucoup plus rapidement et est suffisant pour calculer le nombre de diviseurs.
le_m

A chaque itération, il faut calculer i², ne serait-il pas plus rapide de comparer i avec √n (calculé une seule fois)?
Yukulélé le

10

Cette question intéressante est beaucoup plus difficile qu'il n'y paraît, et elle n'a pas reçu de réponse. La question peut être divisée en 2 questions très différentes.

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

2 donné L, calculer le nombre de combinaisons uniques

Toutes les réponses que je vois jusqu'à présent se réfèrent au n ° 1 et omettent de mentionner qu'il n'est pas traitable pour un nombre énorme. Pour des nombres N de taille moyenne, voire 64 bits, c'est facile; pour un N énorme, le problème d'affacturage peut prendre "une éternité". Le cryptage par clé publique en dépend.

La question n ° 2 nécessite plus de discussion. Si L ne contient que des nombres uniques, il s'agit d'un calcul simple utilisant la formule de combinaison pour choisir k objets parmi n éléments. En fait, vous devez additionner les résultats de l'application de la formule en faisant varier k de 1 à sizeof (L). Cependant, L contiendra généralement plusieurs occurrences de plusieurs nombres premiers. Par exemple, L = {2,2,2,3,3,5} est la factorisation de N = 360. Or ce problème est assez difficile!

En reformulant # 2, étant donné que la collection C contient k éléments, de telle sorte que l'élément a a un "doublon", et l'élément b a b "doublon, etc. Par exemple, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} doivent se produire chacun une et une seule fois si L = {2,2 , 2,3,3,5}. Chaque sous-collection unique de ce type est un diviseur unique de N en multipliant les éléments de la sous-collection.


Voici un lien vers un pseudo-code pour un problème très similaire à 2. answers.google.com/answers/threadview/id/392914.html
mR_fr0g

3
La question n ° 2 a une solution bien connue. Pour une factorisation de {p_i, k_i} où p_iest un facteur premier d'un nombre avec k_imultiplicité, le nombre total de diviseurs de ce nombre est (k_1+1)*(k_2+1)*...*(k_n+1). Je suppose que vous le savez maintenant, mais j'écris ceci pour le bénéfice d'un lecteur aléatoire ici.
Will Ness

9

Une réponse à votre question dépend grandement de la taille de l'entier. Les méthodes pour les petits nombres, par exemple moins de 100 bits, et pour les nombres ~ 1000 bits (comme celles utilisées en cryptographie) sont complètement différentes.


6

JUSTE une ligne
J'ai réfléchi très attentivement à 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 n'avons besoin que d'une ligne de code! (utilisez l'option -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 des nombres de diviseurs, vous pouvez utiliser la fonction très très rapide suivante (fonctionne correctement pour tous les nombres entiers 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 un nombre donné comme un diviseur (fonctionne correctement pour tous les nombres entiers 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 fonctionnent correctement pour tous les nombres entiers positifs à l'exception des nombres 1 et 2, il est donc fonctionnel pour tous les nombres supérieurs à 2, mais si vous devez 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 :)


5

Le tamis d'Atkin est une version optimisée du tamis d'Eratosthène qui donne tous les nombres premiers jusqu'à un entier donné. Vous devriez pouvoir chercher sur Google pour plus de détails.

Une fois que vous avez cette liste, il est simple de diviser votre nombre par chaque nombre premier pour voir s'il s'agit d'un diviseur exact (c'est-à-dire que le reste est égal à zéro).

Les étapes de base pour calculer les diviseurs pour un nombre (n) sont [ceci est un pseudocode converti à partir de code réel donc j'espère ne pas avoir introduit d'erreurs]:

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

5

Vous pourriez essayer celui-ci. C'est un peu hackish, mais c'est raisonnablement rapide.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)

2
Bien que cette fonction fournisse une décomposition en facteurs premiers de n en un temps raisonnable, elle n'est a) pas optimale et b) ne calcule pas le nombre de diviseurs d'un nombre donné selon la question de OP
le_m

Et ne fonctionnera pas pour les grands nombres à cause de sa récursivité
whackamadoodle3000

Bien que ce ne soit pas optimal, et plutôt que de compter les facteurs, il les énumère en fait, la simplicité et la beauté de cela sont étonnantes et raisonnablement rapides. ^^
Gaurav Singhal

5

Une fois que vous avez la factorisation première, il existe un moyen de trouver le nombre de diviseurs. Ajoutez un à chacun des exposants de chaque facteur individuel, puis multipliez les exposants ensemble.

Par exemple: 36 Factorisation premier: 2 ^ 2 * 3 ^ 2 Diviseurs: 1, 2, 3, 4, 6, 9, 12, 18, 36 Nombre de diviseurs: 9

Ajoutez un à chaque exposant 2 ^ 3 * 3 ^ 3 Multipliez les exposants: 3 * 3 = 9


3

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

Il y a quelque temps, il y avait une question principale et j'ai fait un test de temps - pour les entiers 32 bits au moins, déterminer si c'était prime était plus lent que la force brute. Il existe deux facteurs:

1) Alors qu'un humain prend un certain temps pour faire une division, il est très rapide sur l'ordinateur - similaire au coût de recherche de la réponse.

2) Si vous n'avez pas de table principale, vous pouvez créer une boucle qui s'exécute entièrement dans le cache L1. Cela le rend plus rapide.


3

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

2

Les diviseurs 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 n'ai fait aucune recherche approfondie à ce sujet, mais j'ai résolu le problème 12 du projet Euler sur les nombres triangulaires . Ma solution pour le test des diviseurs supérieurs à 500 a duré 309504 microsecondes (~ 0,3 s). 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;
}

À chaque algorithme, il y a un point faible. Je pensais que c'était faible par rapport aux nombres premiers. Mais comme les nombres triangulaires ne sont pas imprimés, il a parfaitement rempli son rôle. D'après mon profilage, je pense que ça s'est plutôt bien passé.

Joyeuses fêtes.


1
Vous auriez une division par 0 sur la première itération ici
barfoon

Malheureusement non. le ++ i est différent de i ++ (ce qui entraînerait une erreur de division par zéro)
iGbanam

J'ai écrit votre fonction en PHP et l'ai exécutée - voici ce que j'ai obtenu - i.minus.com/iKzuSXesAkpbp.png
barfoon

pour une raison étrange, cela a parfaitement fonctionné pour moi. eh bien, mon mal. start numberOfDivisorset l'itérateur à 1; cela devrait éliminer l'erreur de division par zéro
iGbanam

1
Votre algorithme ne fonctionne pas pour les carrés parfaits. Par exemple, il renvoie 4 pour l'entrée x = 4, car il compte 2 deux fois ... 1, 2, 2, 4. La réponse doit être 3: 1,2,4
Michael

1

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


1
Cela va vous amener les nombres premiers en dessous de votre nombre donné - mais il n'est pas garanti que ces nombres premiers seront des diviseurs? (sauf si je manque quelque chose)
Andrew Edgecombe

C'est un saut rapide d'ici pour trouver tous les nombres premiers <sqrt (N) qui divisent également N.
SquareCog

1
Cela peut être un saut rapide, mais tester tous les nombres premiers <sqrt (N) est toujours une mauvaise technique de factorisation, quelle que soit l'efficacité avec laquelle vous les trouvez. Il existe de nombreuses façons d'améliorer cela.
user11318

Tester les nombres premiers est O (N), c'est trouver les nombres premiers qui est la partie la plus difficile. Mais même avec le tamis non optimisé d'ératosthène, vous pouvez toujours trouver tous les nombres premiers sous quelques millions en moins d'une seconde. Cela couvre n'importe quel nombre 64b, et je suis sûr que nous ne parlons pas ici de factoriser des éléments de niveau crypto
Matthew Scharley

1

la méthode des nombres premiers est ici très claire. P [] est une liste de nombres premiers inférieurs ou égaux à 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  .

1

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

Notons maintenant que pour pa prime, τ (p ** k) = k + 1 (les puissances de p). Ainsi, vous pouvez facilement calculer τ (n) à partir de sa factorisation.

Cependant, la factorisation de grands nombres peut être lente (la sécurité de la crytopraphie RSA dépend du produit de deux grands nombres premiers difficile à factoriser). Cela suggère cet algorithme optimisé

  1. Teste si le nombre est premier (rapide)
  2. Si oui, retournez 2
  3. Sinon, factorisez le nombre (lent si plusieurs grands facteurs premiers)
  4. Calculer τ (n) à partir de la factorisation

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 fonctionnera correctement pour les nombres qui sont des carrés parfaits ainsi que pour les nombres qui ne sont pas des carrés parfaits.

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

Notez que stocker la limite supérieure dans une variable séparée fait également gagner du temps, vous ne devez pas appeler la fonction sqrt dans la section condition de la boucle for, cela économise également 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 la boucle for ci-dessus, vous pouvez également utiliser la boucle suivante qui est encore plus efficace car cela élimine le besoin de trouver la racine carrée du nombre.

for(i=2;i*i<=n;i++)
{
    ...
}

1

Voici une fonction que j'ai écrite. sa pire complexité en temps est O (sqrt (n)), le meilleur temps en revanche est O (log (n)). Il vous donne tous les diviseurs premiers ainsi que le nombre de ses occurrences.

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

Je ne sais pas ce que cette fonction calcule, mais ce n'est certainement pas la liste des diviseurs de n.
le_m

1

C'est le moyen le plus simple de calculer les diviseurs de nombres:

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

    }
}

1

@Kendall

J'ai testé votre code et apporté quelques améliorations, maintenant c'est encore plus rapide. J'ai aussi testé avec le 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;
}

0

N'est-ce pas juste une question de factoriser le nombre - de déterminer tous les facteurs du nombre? Vous pouvez ensuite décider si vous avez besoin de toutes les combinaisons d'un ou plusieurs facteurs.

Ainsi, un algorithme possible serait:

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

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


0

C'est quelque chose que j'ai proposé sur la base de la réponse de Justin. Cela peut 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))

0

Je pense que c'est ce que vous recherchez, je fais exactement ce que vous avez demandé. Copiez et collez-le dans le bloc-notes.Save as * .bat.Run.Enter Number.Multiply le processus par 2 et c'est le nombre de diviseurs.Je l'ai fait exprès pour qu'il détermine les diviseurs plus rapidement:

Veuillez noter qu'une variable CMD ne peut pas prendre en charge les valeurs supérieures à 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

882161280-1282 diviseurs
dondon

0

je suppose que celui-ci sera à la fois pratique et précis

script.pyton

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


0

Essayez quelque chose du genre:

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

-1

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

  • Créez une table de nombres premiers pour trouver tous les nombres premiers inférieurs ou égaux à la racine carrée du nombre (Personnellement, j'utiliserais le tamis d'Atkin)
  • Comptez tous les nombres premiers inférieurs ou égaux à la racine carrée du nombre et multipliez cela par deux. Si la racine carrée du nombre est un entier, soustrayez-en un de la variable count.

Devrait fonctionner \ o /

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


2
Je suis confus. Compter tous les nombres premiers inférieurs à la racine carrée d'un nombre ne vous donnera pas ses diviseurs ... tous les nombres premiers inférieurs à la racine carrée d'un nombre ne seront pas tous un diviseur pour ce nombre.
Garrett Berg
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.