2010-09-05 22 views
20

Wenn Sie bereits die Primfaktorzerlegung einer Zahl haben, was ist der einfachste Weg, die Menge aller Faktoren dieser Zahl zu erhalten? Ich weiß, ich könnte einfach von 2 nach sqrt (n) laufen und alle teilbaren Zahlen finden, aber das scheint ineffizient, da wir bereits die Primfaktorzerlegung haben.Generieren aller Faktoren einer Zahl angesichts ihrer Primfaktorzerlegung

Ich denke, es ist im Grunde eine modifizierte Version einer Kombination/wählen Funktion, aber alles, was ich finden kann, ist Methoden zum Zählen der Anzahl der Kombinationen und Möglichkeiten zum Zählen der Anzahl der Faktoren, nicht um die Kombinationen zu generieren/Faktoren.

+0

Verwandte Frage (Python): http://stackoverflow.com/questions/3643725/i-have-a-python-list-of-the-prime-factors-of-a-number-how- do-i-pythonisch-fi – tzot

+0

vgl. http://stackoverflow.com/questions/29992904/enumerate-factors-of-a-number-directly-in-ascending-order-without-sorting/30181351#30181351 –

Antwort

26

Stellen Sie sich vor, große Teiler sind Kugeln in einem Eimer. Wenn zum Beispiel die Hauptteiler Ihrer Zahlen 2, 2, 2, 3 und 7 sind, können Sie 0, 1, 2 oder 3 Instanzen von "Ball 2" nehmen. In ähnlicher Weise können Sie "Ball 3" 0 oder 1 Mal und "Ball 7" 0 oder 1 Mal nehmen.

Jetzt, wenn Sie "Ball 2" zweimal und "Ball 7" einmal nehmen, erhalten Sie Divisor 2 * 2 * 7 = 28. Ebenso, wenn Sie keine Bälle nehmen, erhalten Sie Divisor 1 und wenn Sie alle Bälle nehmen Sie erhalten den Divisor 2 * 2 * 2 * 3 * 7, der gleich der Nummer ist.

Und endlich, um alle möglichen Kombinationen von Kugeln, die Sie aus dem Eimer nehmen können, können Sie leicht Rekursion verwenden.

void findFactors(int[] primeDivisors, int[] multiplicity, int currentDivisor, long currentResult) { 
    if (currentDivisor == primeDivisors.length) { 
     // no more balls 
     System.out.println(currentResult); 
     return; 
    } 
    // how many times will we take current divisor? 
    // we have to try all options 
    for (int i = 0; i <= multiplicity[currentDivisor]; ++i) { 
     findFactors(primeDivisors, multiplicity, currentDivisor + 1, currentResult); 
     currentResult *= primeDivisors[currentDivisor]; 
    } 
} 

Jetzt können Sie es oben Beispiel laufen auf:

findFactors(new int[] {2, 3, 7}, new int[] {3, 1, 1}, 0, 1); 
+4

+1 für die Erklärung in Ihrem ersten Absatz.:-) – ShreevatsaR

+2

Sie müssen die Multiplizitäten nicht kennen, nur den Wert von n. Multiplikation mit der aktuellen Primzahl, während "currentResult" n teilt. –

+0

Danke, sehr hilfreich! – dimo414

4

dimo414, in der Regel eine sehr schwierige Aufgabe betrachtet Faktoren zu erzeugen. In der Tat beruht der Schutz der meisten Ihrer wichtigen Vermögenswerte (d. H. Geld, Informationen usw.) auf der einfachen, aber äußerst schwierigen Aufgabe, eine Nummer zu faktorisieren. Siehe diesen Artikel zum RSA-Verschlüsselungsschema http://en.wikipedia.org/wiki/RSA_(cryptosystem). Ich schweife ab.

Um Ihre Frage zu beantworten, ist ein kombinatorischer Ansatz Ihre beste Methode, wie von Nikita hervorgehoben (übrigens, Kudos zu Ihrer Erklärung).

Ich weiß, ich könnte nur Schleife von 2 bis sqrt (n) und finden Sie alle teilbar Zahlen

Viele Menschen wegen der sehr ähnlichen Konzept zu diesem Schluss springen mit der Erzeugung von Primzahlen verbunden. Leider ist das falsch, da Sie mehrere Faktoren übersehen werden, die größer sind als die sqrt (n), die keine Primzahlen sind (ich lasse Sie das selbst beweisen).

Um nun die Anzahl der Faktoren für eine gegebene Zahl n zu bestimmen, betrachten wir die Primfaktorzerlegung von n. Wenn n = p ein, dann wissen wir, dass n (a + 1) Faktoren (1, p, p ..., S. ein) haben wird. Dies ist der Schlüssel zur Bestimmung der Gesamtzahl der Faktoren.Wenn n mehrere Primfaktoren hatte, sagen

n = p ein& middot; p b& middot; & middot; p kr

dann mit der Produktregel des Zählens (http://en.wikipedia.org/wiki/Rule_of_product), wissen wir, dass es

m = (a + 1) & middot sein wird; (b + 1) & middot; & middot; (r + 1)

Faktoren. Jetzt müssen wir nur noch jede mögliche Kombination der Zahlen finden, die uns die Primfaktorzerlegung gegeben hat. Unten ist ein Code in R, der hoffentlich demonstriert, was ich erklärt habe.

Der erste Teil meines Codes macht eine einfache Überprüfung der Primalität, denn wenn die Zahl prim ist, sind die einzigen Faktoren 1 und selbst. Als nächstes, wenn die Zahl keine Primzahl ist und größer als 1 ist, habe ich zunächst die Primfaktorzerlegung der Zahl finden, sagen wir,

n = p ein& middot; p b& middot; & middot; p kr

I dann nur die eindeutigen Primzahlen UniPrimes labled finden, so für dieses Beispiel UniPrimes enthalten würde (p , p , p k). Ich finde dann alle Mächte jeder Primzahl und füge sie zu einem Array hinzu, das mit MyFactors gekennzeichnet ist. Nachdem dieses Array erstellt wurde, finde ich jede mögliche Produktkombination der Elemente in MyFactors. Schließlich füge ich 1 zum Array hinzu (da es ein trivialer Faktor ist) und sortiere es. Voila! Es ist extrem schnell und funktioniert für sehr große Zahlen mit vielen Faktoren.

Ich habe versucht, den Code so übersetzbar wie möglich zu anderen Sprachen zu machen (dh ich nehme an, dass Sie bereits eine Funktion erstellt haben, die die Primfaktorzerlegung generiert (oder eine eingebaute Funktion verwendet) und eine Primzahl-Testfunktion.) und ich habe keine speziellen integrierten Funktionen verwendet, die für R einzigartig sind. Lassen Sie mich wissen, wenn etwas nicht klar ist. Prost!

factor2 <- function(MyN) { 

    CheckPrime <- isPrime(MyN) 

    if (CheckPrime == F && !(MyN == 1)) { 
      MyPrimes <- primeFactors(MyN) 
      MyFactors <- vector() 
      MyPowers <- vector() 
      UniPrimes <- unique(MyPrimes) 
        for (i in 1:length(UniPrimes)) { 

          TempSize <- length(which(MyPrimes == UniPrimes[i])) 

          for (j in 1:TempSize) { 
            temp <- UniPrimes[i]^j 
            MyPowers <- c(MyPowers, temp) 
          } 

        } 
      MyFactors <- c(MyFactors, MyPowers) 
      MyTemp <- MyPowers 
      MyTemp2 <- vector() 
      r <- 2 
      while (r <= length(UniPrimes)) { 

        i <- 1L 

        while (i <= length(MyTemp)) { 
          a <- which(MyPrimes > max(primeFactors(MyTemp[i]))) 
            for (j in a) { 
              temp <- MyTemp[i]*MyPowers[j] 
              MyFactors <- c(MyFactors, temp) 
              MyTemp2 <- c(MyTemp2, temp) 
            } 
          i <- i + 1 
        } 
        MyTemp <- MyTemp2 
        MyTemp2 <- vector() 
        r <- r + 1 
      } 
    } else { 
      if (MyN == 1) { 
        MyFactors <- vector() 
      } else { 
        MyFactors <- MyN 
      } 
    } 
    MyFactors <- c(1, MyFactors) 
    sort(MyFactors) 
} 
Verwandte Themen