Αλγόριθμος για τον υπολογισμό του αριθμού των διαιρέτες ενός συγκεκριμένου αριθμού

ψήφοι
163

Ποια θα ήταν η βέλτιστη αλγόριθμο (απόδοση-σοφός) για τον υπολογισμό του αριθμού των διαιρέτες ενός συγκεκριμένου αριθμού;

Θα είναι μεγάλο εάν θα μπορούσε να προσφέρει ψευδοκώδικα ή μια σύνδεση με κάποιο παράδειγμα.

EDIT: Όλες οι απαντήσεις ήταν πολύ χρήσιμη, σας ευχαριστώ. Είμαι εφαρμογή της Κόσκινο του Atkin και, στη συνέχεια, Πάω να χρησιμοποιήσει κάτι παρόμοιο με αυτό που ανέφερε ο Jonathan Leffler. Ο σύνδεσμος δημοσιεύτηκε από τον Justin Bozonier έχει περισσότερες πληροφορίες για αυτό που ήθελα.

Δημοσιεύθηκε 21/09/2008 στις 06:44
πηγή χρήστη
Σε άλλες γλώσσες...                            


28 απαντήσεις

ψήφοι
1

Θέλετε το Κόσκινο του Atkin, που περιγράφονται εδώ: http://en.wikipedia.org/wiki/Sieve_of_Atkin

Απαντήθηκε 21/09/2008 στις 06:53
πηγή χρήστη

ψήφοι
0

Αυτό δεν είναι μόνο θέμα factoring τον αριθμό - τον καθορισμό όλους τους παράγοντες του αριθμού; Μπορείτε στη συνέχεια να αποφασίσει αν θα πρέπει να έχετε όλους τους συνδυασμούς ενός ή περισσοτέρων παραγόντων.

Έτσι, μια πιθανή αλγόριθμο θα είναι:

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

Στη συνέχεια είναι στο χέρι σας να συνδυάσει τα στοιχεία για να καθορίσει το υπόλοιπο της απάντησης.

Απαντήθηκε 21/09/2008 στις 06:59
πηγή χρήστη

ψήφοι
74

Dmitriy είναι σωστό ότι θα θελήσετε το κόσκινο της Atkin για να δημιουργήσει την προνομιακή λίστα, αλλά δεν πιστεύω ότι φροντίζει για το όλο θέμα. Τώρα που έχετε μια λίστα των πρώτων αριθμών θα πρέπει να δούμε πόσα από αυτά πρώτων δρα ως διαιρέτης (και πόσο συχνά).

Εδώ είναι μερικά python για την algo Κοιτάξτε εδώ και την αναζήτηση για το «Θέμα: μαθηματικά - αλγόριθμο ανάγκη διαιρέτες». Απλά μετρήστε τον αριθμό των στοιχείων της λίστας, αντί όμως να τα επιστρέψει.

Εδώ είναι μια Dr. Math που εξηγεί τι ακριβώς είναι αυτό που πρέπει να κάνουμε μαθηματικά.

Ουσιαστικά αυτό σημαίνει ότι πρέπει να αν ο αριθμός σας nείναι:
n = a^x * b^y * c^z
(όπου α, β, και γ είναι n είναι πρώτοι διαιρέτες και x, y, και z είναι ο αριθμός των φορών που διαιρέτη επαναλαμβάνεται), τότε ο συνολικός αριθμός για το σύνολο των διαιρετών είναι:
(x + 1) * (y + 1) * (z + 1).

Επεξεργασία: BTW, να βρείτε ένα, β, γ, κλπ θα θελήσετε να κάνετε αυτό που ισοδυναμεί με ένα άπληστο algo αν είμαι κατανόηση αυτό σωστά. Ξεκινήστε με το μεγαλύτερο πρώτο διαιρέτη σας και να πολλαπλασιάζεται από μόνο του, μέχρι περαιτέρω πολλαπλασιασμό θα υπερβαίνει τον αριθμό n. Στη συνέχεια, να προχωρήσουμε στο επόμενο χαμηλότερο συντελεστή και τους χρόνους του προηγούμενου προνομιακή ^ αριθμό των φορών που πολλαπλασιάστηκε με την τρέχουσα προνομιακή και να κρατήσει τον πολλαπλασιασμό από τον κύριο μέχρι την επόμενη θα υπερβεί ν ... κλπ Παρακολουθήστε τον αριθμό των φορών που πολλαπλασιάζουν το διαιρέτες μαζί και εφαρμόζουν αυτές τις αριθμούς στον τύπο ανωτέρω.

Δεν είναι 100% σίγουρος για algo περιγραφή μου, αλλά αν αυτό δεν είναι αυτό είναι κάτι παρόμοιο.

Απαντήθηκε 21/09/2008 στις 07:03
πηγή χρήστη

ψήφοι
-1

Δεν ξέρω η πιο αποτελεσματική μέθοδος, αλλά θα ήθελα να κάνω την εξής:

  • Δημιουργήστε έναν πίνακα των πρώτων αριθμών για να βρείτε όλους τους πρώτους μικρότερη ή ίση με την τετραγωνική ρίζα του αριθμού (Προσωπικά, είχα χρησιμοποιήσει το Κόσκινο του Atkin)
  • Μετρήστε όλους τους πρώτους μικρότερη ή ίση με την τετραγωνική ρίζα του αριθμού και πολλαπλασιάστε το με δύο. Εάν η τετραγωνική ρίζα του αριθμού είναι ένας ακέραιος, τότε αφαιρέσουμε την μία από τη μεταβλητή καταμέτρηση.

Θα πρέπει να εργαστεί \ o /

Αν χρειαστεί, μπορώ να κωδικοποιήσει κάτι μέχρι αύριο το C για να αποδειχθεί.

Απαντήθηκε 21/09/2008 στις 07:16
πηγή χρήστη

ψήφοι
5

Το κόσκινο του Atkin είναι μια βελτιωμένη έκδοση του κόσκινου του Ερατοσθένη που δίνει όλους τους πρώτους αριθμούς μέχρι ένα δεδομένο ακέραιο αριθμό. Θα πρέπει να είναι σε θέση να google αυτό για περισσότερες λεπτομέρειες.

Μόλις έχετε τον κατάλογο αυτό, είναι ένα απλό θέμα να διαιρέσει τον αριθμό σας από κάθε κύριο για να δούμε αν είναι μια ακριβής διαιρέτης (δηλαδή, το υπόλοιπο είναι μηδέν).

Τα βασικά βήματα για τον υπολογισμό των διαιρέτες για έναν αριθμό (n) είναι [αυτό ψευδοκώδικα μετατραπεί από πραγματικό κώδικα, έτσι ελπίζω να μην έχουν εισαχθεί σφάλματα]:

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
Απαντήθηκε 21/09/2008 στις 07:36
πηγή χρήστη

ψήφοι
46

Υπάρχουν πολλές περισσότερες τεχνικές στο factoring από το κόσκινο της Atkin. Για παράδειγμα, ας υποθέσουμε ότι θέλουμε να παράγοντα 5893. Λοιπόν sqrt του είναι 76,76 ... Τώρα θα προσπαθήσω να γράψω 5893 ως προϊόν των τετραγώνων. Καλά (77 * 77 - 5893) = 36, η οποία είναι 6 στο τετράγωνο, έτσι 5893 = 77 * 77 - 6 * 6 = (77 + 6 ) (77-6) = 83 * 71 . Αν αυτό δεν λειτούργησε θα είχαμε εξετάσει κατά πόσον 78 * 78 με 5893 ήταν ένα τέλειο τετράγωνο. Και ούτω καθεξής. Με την τεχνική αυτή μπορείτε να δοκιμάσουν γρήγορα για παράγοντες κοντά στην τετραγωνική ρίζα του n πολύ πιο γρήγορα από ό, τι με τη δοκιμή μεμονωμένων πρώτων αριθμών. Αν συνδυάσουμε αυτή την τεχνική για τον αποκλεισμό των μεγάλων πρώτων αριθμών με ένα κόσκινο, θα έχετε μια πολύ καλύτερη μέθοδος factoring από ό, τι με το κόσκινο και μόνο.

Και αυτό είναι μόνο ένα από τα πολλά τεχνικές που έχουν αναπτυχθεί. Αυτή είναι μια αρκετά απλή. Θα σας πάρει πολύ χρόνο για να μάθουν, ας πούμε, αρκετά θεωρία αριθμών για να κατανοήσουν τις τεχνικές factoring βασισμένων σε ελλειπτικές καμπύλες. (Ξέρω ότι υπάρχουν. Δεν τους καταλαβαίνω.)

Ως εκ τούτου, εκτός αν έχουμε να κάνουμε με μικρές ακέραιους αριθμούς, δεν θα προσπαθήσει να λύσει αυτό το πρόβλημα ο ίδιος. Αντ 'αυτού θα ήθελα να προσπαθήσουμε να βρούμε έναν τρόπο να χρησιμοποιήσουν κάτι σαν το PARI βιβλιοθήκη που έχει ήδη μια πολύ αποτελεσματική λύση που υλοποιήθηκε. Με αυτό μπορώ να παράγοντας έναν τυχαίο 40-ψήφιο αριθμό, όπως 124321342332143213122323434312213424231341 σε περίπου 0,05 δευτερόλεπτα. (Παραγοντοποίηση του, σε περίπτωση που αναρωτήθηκε, είναι 439 * 29 * 1321 * 157 907 * 284,749 * 33.843.676.813 * 4857795469949. Είμαι αρκετά σίγουρος ότι δεν το καταλάβουν αυτό χρησιμοποιώντας το κόσκινο των Atkin ...)

Απαντήθηκε 21/09/2008 στις 09:47
πηγή χρήστη

ψήφοι
9

Μια απάντηση στην ερώτησή σας εξαρτάται σε μεγάλο βαθμό από το μέγεθος του ακεραίου. Μέθοδοι για μικρούς αριθμούς, π.χ. λιγότερο από 100 bit, και για τους αριθμούς ~ 1000 bit (όπως χρησιμοποιείται στην κρυπτογραφία) είναι εντελώς διαφορετικά.

Απαντήθηκε 21/09/2008 στις 19:38
πηγή χρήστη

ψήφοι
27

Διαφωνώ ότι το κόσκινο της Atkin είναι ο τρόπος να πάει, διότι θα μπορούσε εύκολα να πάρει περισσότερο χρόνο για να ελέγξετε κάθε αριθμό [1, n] για primality από ό, τι θα ήταν να μειωθεί ο αριθμός από διαιρέσεις.

Εδώ είναι μερικά κωδικό που, αν και ελαφρώς hackier, είναι γενικά πολύ πιο γρήγορα:

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 που δουλεύει κώδικα python για να λύσει αυτό το πρόβλημα.

Απαντήθηκε 23/09/2008 στις 02:53
πηγή χρήστη

ψήφοι
10

Αυτή η ενδιαφέρουσα ερώτηση είναι πολύ πιο δύσκολο από ό, τι φαίνεται, και δεν έχει απαντηθεί. Το ερώτημα μπορεί να υπολογιστεί στις 2 πολύ διαφορετικές ερωτήσεις.

1 δίνεται Ν, βρείτε τη λίστα L των πρώτων παραγόντων Ν του

2 δεδομένη L, υπολογίζει τον αριθμό των μοναδικών συνδυασμών

Όλες οι απαντήσεις που βλέπω μέχρι τώρα αφορούν # 1 και παραλείπουν να αναφέρουν ότι δεν είναι προσιτό για τους τεράστιους αριθμούς. Για μετρίως μεγέθους Ν, ακόμα και 64-bit αριθμούς, είναι εύκολο? για την τεράστια Ν, το πρόβλημα factoring μπορεί να πάρει «για πάντα». Δημόσια κλειδί κρυπτογράφησης εξαρτάται από αυτό.

Ερώτηση # 2 χρειάζεται περισσότερη συζήτηση. Εάν L περιέχει μόνο μοναδικούς αριθμούς, είναι ένας απλός υπολογισμός με χρήση του τύπου συνδυασμού για την επιλογή k αντικειμένων από n αντικείμενα. Στην πραγματικότητα, θα πρέπει να συνοψίσουμε τα αποτελέσματα από την εφαρμογή του τύπου ενώ μεταβάλλεται k από 1 έως sizeof (L). Ωστόσο, L θα περιέχει συνήθως πολλαπλές εμφανίσεις των πολλαπλών πρώτων. Για παράδειγμα, L = {2,2,2,3,3,5} είναι η παραγοντοποίηση του Ν = 360. Τώρα το πρόβλημα αυτό είναι αρκετά δύσκολο!

Επαναδιατύπωση # 2, δεδομένου συλλογή C που περιέχει k στοιχεία, έτσι ώστε το στοιχείο Α έχει «εις διπλούν, και το στοιχείο β έχει β» αντίγραφα, κτλ πόσοι μοναδικοί συνδυασμοί από 1 έως k-1 αντικείμενα υπάρχουν; Για παράδειγμα, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} πρέπει να συμβεί κάθε φορά και μόνο μία φορά αν L = {2,2 , 2,3,3,5}. Κάθε τέτοια μοναδική υπο-συλλογή είναι ένα μοναδικό διαιρέτης του Ν πολλαπλασιάζοντας τα στοιχεία στο υπο-συλλογή.

Απαντήθηκε 04/11/2008 στις 03:52
πηγή χρήστη

ψήφοι
5

Μπορείτε να δοκιμάσετε αυτό το ένα. Είναι λίγο hackish, αλλά είναι λογικά γρήγορα.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
Απαντήθηκε 18/07/2009 στις 04:31
πηγή χρήστη

ψήφοι
3

Πριν να δεσμευτούν για μια λύση θεωρούν ότι η προσέγγιση Κόσκινο δεν θα μπορούσε να είναι μια καλή απάντηση στην τυπική περίπτωση.

Α, ενώ πίσω υπάρχει ένα πρωταρχικό ερώτημα και έκανα ένα τεστ χρόνο - για ακέραιους 32-bit τουλάχιστον τον προσδιορισμό αν ήταν προνομιακή ήταν πιο αργή από την ωμή βία. Υπάρχουν δύο παράγοντες σε εξέλιξη:

1) Αν ένας άνθρωπος παίρνει λίγο χρόνο για να κάνει μια διαίρεση είναι πολύ γρήγορη στον υπολογιστή - παρόμοιο με το κόστος που αναζητούν την απάντηση.

2) Εάν δεν έχετε μια προνομιακή πίνακα μπορείτε να κάνετε μια θηλιά που τρέχει εξ ολοκλήρου στην κρυφή μνήμη L1. Αυτό καθιστά πιο γρήγορα.

Απαντήθηκε 18/07/2009 στις 05:11
πηγή χρήστη

ψήφοι
5

Μόλις έχετε την παραγοντοποίηση, υπάρχει ένας τρόπος για να βρείτε τον αριθμό των διαιρέτες. Προσθέστε ένα σε κάθε μία από τις εκθέτες για κάθε παράγοντα και στη συνέχεια πολλαπλασιάστε τα εκθέτες από κοινού.

Για παράδειγμα: 36 παραγοντοποίηση: 2 ^ 2 * 3 ^ 2 διαιρέτες: 1, 2, 3, 4, 6, 9, 12, 18, 36 Αριθμός divisors: 9

Προσθέστε ένα σε κάθε εκθέτη 2 ^ 3 * 3 ^ 3 Πολλαπλασιασμός εκθέτες: 3 * 3 = 9

Απαντήθηκε 02/02/2010 στις 01:28
πηγή χρήστη

ψήφοι
2

Διαιρέτες κάνει κάτι θεαματικό: διαιρούν εντελώς. Αν θέλετε να ελέγξετε τον αριθμό των διαιρέτες ενός αριθμού, n, είναι σαφές ότι είναι περιττό να καλύπτουν όλο το φάσμα, 1...n. Δεν έχω κάνει καμία έρευνα σε βάθος για αυτό, αλλά εγώ λυθεί το πρόβλημα έργο του Euler 12 σε Τριγωνικό αριθμούς . Η λύση μου για το μεγαλύτερο από 500 διαιρέτες δοκιμή έτρεξε για 309 504 μικροδευτερόλεπτα (~ 0.3s). Έγραψα αυτή τη λειτουργία διαιρέτη για τη λύση.

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

Για κάθε αλγόριθμο, υπάρχει ένα αδύνατο σημείο. Σκέφτηκα ότι αυτό ήταν αδύναμη κατά τους πρώτους αριθμούς. Αλλά δεδομένου ότι τριγωνική αριθμοί δεν είναι εκτύπωση, εξυπηρέτησε το σκοπό του άψογα. Από το προφίλ μου, πιστεύω ότι έκανα αρκετά καλά.

Καλές διακοπές.

Απαντήθηκε 30/12/2010 στις 22:19
πηγή χρήστη

ψήφοι
33

@Yasky

διαιρέτες λειτουργία σας έχει ένα bug στο ότι δεν λειτουργεί σωστά για τέλεια τετράγωνα.

Προσπαθήστε:

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;
}
Απαντήθηκε 23/03/2011 στις 15:32
πηγή χρήστη

ψήφοι
6

Μόλις μία γραμμή
που έχω σκεφτεί πολύ επιμελώς για την ερώτησή σας και προσπάθησα να γράψω ένα υψηλής απόδοσης και αποδοτικοί κομμάτι του κώδικα για να εκτυπώσετε όλες τις διαιρέτες ενός συγκεκριμένου αριθμού στην οθόνη χρειαζόμαστε μόνο μία γραμμή κώδικα! (δυνατότητα χρήσης -std = C99, ενώ την κατάρτιση μέσω του 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

για την εύρεση του αριθμού των διαιρέτες μπορείτε να χρησιμοποιήσετε την ακόλουθη πολύ πολύ γρήγορη λειτουργία (το έργο σωστά για όλους ακέραιο αριθμό, εκτός από 1 και 2)

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

ή Αν θεραπεία δεδομένο αριθμό ως διαιρέτης (λειτουργούν σωστά για όλους ακέραιο αριθμό, εκτός από 1 και 2)

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

ΣΗΜΕΙΩΣΗ: δύο παραπάνω λειτουργίες λειτουργεί σωστά για όλα θετικός ακέραιος αριθμός, εκτός από τον αριθμό 1 και 2, ώστε να είναι λειτουργική για όλους τους αριθμούς που είναι μεγαλύτεροι από το 2, αλλά αν πρέπει να καλύψει 1 και 2, μπορείτε να χρησιμοποιήσετε μία από τις ακόλουθες λειτουργίες (λίγο βραδύτερη)

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

Ή

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

το μικρό είναι όμορφο :)

Απαντήθηκε 11/11/2011 στις 03:59
πηγή χρήστη

ψήφοι
1

η μέθοδος πρώτος αριθμός είναι πολύ σαφής εδώ. Ρ [] είναι ένας κατάλογος των πρώτος αριθμός μικρότερος ή ίσος του 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  .
Απαντήθηκε 10/01/2013 στις 00:12
πηγή χρήστη

ψήφοι
8

Εδώ είναι μια ευθεία προς τα εμπρός O (sqrt (n)) αλγόριθμο. Θα χρησιμοποιηθεί αυτό για να λύσει 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  
Απαντήθηκε 05/04/2013 στις 05:32
πηγή χρήστη

ψήφοι
1

εγχειρίδια Θεωρία Αριθμών καλέσετε τη λειτουργία ταυ διαιρέτη-καταμέτρηση. Το πρώτο ενδιαφέρον γεγονός είναι ότι είναι πολλαπλασιαστική, δηλαδή. τ (ab) = τ (α) τ (β), όταν τα α και b δεν έχουν κοινό παράγοντα. (Απόδειξη: κάθε ζεύγος διαιρέτες των a και b δίνει μια ξεχωριστή διαιρέτης του ab).

Τώρα σημειώστε ότι για pa προνομιακή, τ (p ** k) = k + 1 (οι δυνάμεις της σ). Έτσι μπορείτε εύκολα να υπολογίσουμε τ (n) από παραγοντοποίησης της.

Ωστόσο factorising μεγάλους αριθμούς μπορεί να είναι αργή (η ασφάλεια του RSA crytopraphy εξαρτάται από το προϊόν των δύο μεγάλων πρώτων αριθμών είναι δύσκολο να factorise). Αυτό δείχνει ότι αυτό το βελτιστοποιημένο αλγόριθμο

  1. Δοκιμή αν ο αριθμός είναι πρώτος (γρήγορη)
  2. Αν ναι, επιστρέψτε 2
  3. Σε αντίθετη περίπτωση, factorise τον αριθμό (αργή εάν πολλές μεγάλες πρωταρχικούς παράγοντες)
  4. Υπολογίστε τ (n) από το factorisation
Απαντήθηκε 14/07/2013 στις 13:15
πηγή χρήστη

ψήφοι
1

Το παρακάτω είναι ένα πρόγραμμα C για να βρείτε τον αριθμό των διαιρέτες ενός συγκεκριμένου αριθμού.

Η πολυπλοκότητα του παραπάνω αλγορίθμου είναι O (sqrt (n)).

Αυτός ο αλγόριθμος θα λειτουργήσει σωστά για τον αριθμό που είναι τέλειο τετράγωνο, καθώς και οι αριθμοί που δεν είναι τέλειο τετράγωνο.

Σημειώστε ότι η UPPERLIMIT του βρόχου έχει οριστεί στην τετραγωνικής ρίζας του αριθμού να έχουν τον αλγόριθμο πιο αποτελεσματική.

Να σημειωθεί ότι την αποθήκευση της UPPERLIMIT σε μια ξεχωριστή μεταβλητή επίσης εξοικονομεί το χρόνο, δεν θα πρέπει να καλέσετε τη συνάρτηση sqrt στο τμήμα κατάσταση του βρόχου for, αυτό επίσης εξοικονομεί υπολογιστικό χρόνο σας.

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

Αντί της παραπάνω για βρόχο μπορείτε επίσης να χρησιμοποιήσετε την ακόλουθη βρόχο που είναι ακόμη πιο αποτελεσματικό, καθώς αυτό καταργεί την ανάγκη να βρούμε την τετραγωνική ρίζα του αριθμού.

for(i=2;i*i<=n;i++)
{
    ...
}
Απαντήθηκε 19/08/2014 στις 14:35
πηγή χρήστη

ψήφοι
1

Εδώ είναι μια λειτουργία που έγραψα. είναι χειρότερη χρονική πολυπλοκότητα είναι O (sqrt (n)), καλύτερος χρόνος από την άλλη πλευρά είναι O (log (n)). Αυτό σας δίνει όλα τα κύρια διαιρέτες μαζί με τον αριθμό των εμφάνιση του.

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;
}
Απαντήθηκε 01/12/2014 στις 13:02
πηγή χρήστη

ψήφοι
3

Αυτή είναι μια αποτελεσματική λύση:

#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;
}
Απαντήθηκε 01/12/2014 στις 14:01
πηγή χρήστη

ψήφοι
1

Αυτός είναι ο πιο βασικός τρόπος υπολογισμού των αριθμό 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);

    }
}
Απαντήθηκε 02/12/2014 στις 03:25
πηγή χρήστη

ψήφοι
0

Αυτό είναι κάτι που ήρθε με βάση τις Justin απάντηση. Θα μπορούσε να απαιτήσει κάποια βελτιστοποίηση.

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))
Απαντήθηκε 29/11/2015 στις 07:30
πηγή χρήστη

ψήφοι
0

Νομίζω ότι αυτό είναι αυτό που ψάχνετε for.I κάνει ακριβώς αυτό που ζήτησε. Αντιγραφή και Επικόλληση σε Notepad.Save όπως * .bat.Run.Enter Number.Multiply τη διαδικασία με 2 και thats ο αριθμός των divisors.I έκανε επίτηδες έτσι το να καθορίσει τις διαιρέτες πιο γρήγορα:

Pls να σημειώσετε ότι η ΚΥΑ varriable υπερύψωσης τιμές στήριξης πάνω από 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
Απαντήθηκε 07/02/2016 στις 21:24
πηγή χρήστη

ψήφοι
1

@Kendall

Θα δοκιμαστεί κωδικό σας και έκανε κάποιες βελτιώσεις, τώρα είναι ακόμη πιο γρήγορα. Επίσης, δοκιμάστηκε με @ هومن جاویدپور κώδικα, αυτό είναι επίσης πιο γρήγορα από ό, τι τον κωδικό του.

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;
}
Απαντήθηκε 11/11/2016 στις 15:32
πηγή χρήστη

ψήφοι
0

Υποθέτω ότι αυτό θα είναι χρήσιμο, καθώς και ακριβείς

script.pyton

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

Απαντήθηκε 23/01/2017 στις 15:57
πηγή χρήστη

ψήφοι
0

Δοκιμάστε κάτι προς αυτή την κατεύθυνση:

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;
}
Απαντήθηκε 23/01/2017 στις 16:01
πηγή χρήστη

ψήφοι
0

Μπορείτε να προϋπολογίζουν πρώτων αριθμών μέχρι τη ρίζα sqaure του μέγιστου δυνατού Ν και τον υπολογισμό του εκθέτη του κάθε πρώτος παράγοντας ενός αριθμού. Ο αριθμός των διαιρέτες του n (n = p1 ^ α p2 ^ β p3 ^ γ ...) είναι (α + 1) (β + 1) (γ + 1) επειδή είναι το ίδιο με το να μετρήσει τον τρόπο συνδυάζουν την προνομιακή αριθμοί αυτού παραγόντων (και αυτό θα μετρήσει τον αριθμό των διαιρέτες). Αυτό είναι πολύ γρήγορος, αν προϋπολογίζουν οι πρώτοι αριθμοί

Πιο λεπτομερείς πληροφορίες σχετικά με αυτή τη μέθοδο:

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;
    }
}
Απαντήθηκε 17/12/2017 στις 15:40
πηγή χρήστη

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