Dies ist ein Problem aus der Übungsstunde des polnischen Collegiate Programming Contest 2012 . Obwohl ich die Lösungen für den Hauptwettbewerb finden konnte, kann ich nirgendwo eine Lösung für dieses Problem finden.
Das Problem ist: Wenn eine Menge von verschiedenen positiven ganzen Zahlen nicht größer als 10 9 ist , finden Sie die Größe m der kleinsten Teilmenge, die keinen anderen gemeinsamen Teiler als 1 hat. N ist höchstens 500, und es kann angenommen werden, dass eine Lösung existiert.
Ich konnte zeigen, dass . Meine Argumentation lautet: Angenommen, es gibt eine minimale Teilmenge S der Größe | S | = 10 , mit gcd = 1. Dann müssen alle 9-Teilmengen von S gcd> 1 haben. Es gibt genau 10 solcher Teilmengen, und ihre gcds müssen paarweise koprime sein. Diese gcds seien 1 < g 1 < g 2 < . . . < g 10 , wobei gcd ( g i , g j ) = 1 für i ≠ ist . Danndie maximale Anzahl in S ist , g 2 g 3 . . . g 10 . Aber g 2 g 3 . . . g 10 ≥ 3 × 5 × 7 × 11 × . . . × 29 = 3234846615 > 10 9 , ein Widerspruch.
Trotzdem ist eine unkomplizierte rohe Gewalt immer noch zu langsam. Hat jemand andere Ideen?
quelle
Antworten:
Dieses Problem entspricht dem folgenden und es ist trivial, die Reduktion in beide Richtungen zu konstruieren.
Bestimmen Sie anhand einer Liste von Bitvektoren die minimale Anzahl von ihnen, sodass0 (∗)
and
alle den Bit-Vektor ergeben. ( ∗ )Dann zeigen wir, dass sich die Set-Abdeckung auf reduziert . Mit Satzabdeckung meine ich, wenn eine Liste von Sätzen S 1 , … , S k gegeben ist, die Mindestanzahl von Sätzen zu finden, die ihre Vereinigung abdecken.(∗) S1,…,Sk
Wir um die Elemente in den Sätzen zu . Sei f ( S ) = ( 1 - χ a 1 ( S ) , … , 1 - χ a n ( S ) ) , wobei χ x ( S ) = 1 ist, wenn x ∈ S , sonst 0. Beachten Sie, dass diese Funktion eine Bijektion ist und daher eine Umkehrung aufweist.a1,…,an f(S)=(1−χa1(S),…,1−χan(S)) χx(S)=1 x∈S
Wenn wir nun nach f ( S 1 ) , … , f ( S k ) lösen und die Lösungen { f ( S b 1 ) , … , f ( S b m ) } sind , dann { f - 1 ( S b 1 ) , … , f - 1 ( S b m ) }(∗) f(S1),…,f(Sk) {f(Sb1),…,f(Sbm)} {f−1(Sb1),…,f−1(Sbm)} ist die Lösung, um Deckung zu setzen.
Daher würde ich denken, dass dieses Problem die Fähigkeit testet, den Suchraum zu beschneiden.
quelle
Es ist möglich, dies relativ effizient zu lösen, indem alle paarweisen GCDs berechnet, Duplikate entfernt und dann rekursiv behandelt werden. Es ist der Vorgang des Entfernens von Duplikaten, bevor Sie eine Wiederholung durchführen, die es effizient macht.
Ich werde den Algorithmus im Folgenden näher erläutern , aber zuerst, hilft es , einen binären Operator zu definieren . Wenn S , T Mengen positiver Ganzzahlen sind, definieren Sie⊗ S,T
Beachten Sie, dass und | S ⊗ T | ≤ 10 9 (in Ihrem Problem); Typischerweise ist S ⊗ T sogar kleiner als eine dieser Grenzen vermuten lässt, was dazu beiträgt, den Algorithmus effizienter zu machen. Beachten Sie auch, dass wir S ⊗ T mit | berechnen können S | × | T | GCD-Operationen durch einfache Aufzählung.|S⊗T|≤|S|×|T| |S⊗T|≤109 S⊗T S⊗T |S|×|T|
Mit dieser Notation ist hier der Algorithmus. Sei der eingegebene Satz von Zahlen. Berechnen Sie S 2 = S 1 ⊗ S 1 , dann S 3 = S 1 ⊗ S 2 , dann S 4 = S 1 ⊗ S 3 und so weiter. Finden Sie das kleinste k so, dass 1 ∈ S k aber 1 ∉ S k - 1 ist . Dann wissen Sie, dass die Größe der kleinsten solchen Teilmenge k istS1 S2=S1⊗S1 S3=S1⊗S2 S4=S1⊗S3 k 1∈Sk 1∉Sk−1 k . Wenn Sie auch ein konkretes Beispiel für eine solche Teilmenge ausgeben möchten, können Sie eine solche Menge leicht rekonstruieren, indem Sie Rückzeiger beibehalten.
Dies ist relativ effizient, da keiner der Zwischensätze eine Größe über (tatsächlich wird ihre Größe wahrscheinlich viel kleiner als diese sein) und die Laufzeit etwa 500 × ( | S 1 | + | S 2) erfordert | + ⋯ ) gcd-Operationen.109 500×(|S1|+|S2|+⋯)
Hier ist eine Optimierung, die die Effizienz noch weiter verbessern könnte. Grundsätzlich können Sie iteriertes Verdoppeln verwenden, um das kleinste so zu finden, dass 1 ∈ S k . Insbesondere verfolgen wir für jedes Element x ∈ S i die kleinste Teilmenge von S 1, deren gcd x ist und deren Größe ≤ i ist . (Wenn Sie Duplikate entfernen, lösen Sie Bindungen zugunsten der Teilmenge auf, die kleiner ist.) Anstatt nun die Folge von neun Mengen S 1 , S 2 , S 3 , S 4 , zu berechnen ,k 1∈Sk x∈Si S1 x ≤i , wir stattdessen die Sequenz der fünf Sätze berechnen S 1 , S 2 , S 4 , S 8 , S 9 , durch Berechnen von S 2 = S 1 ⊗ S 1 , dann S 4 = S 2 ⊗ S 2 , dann S 8 = S 4 ⊗ S 4 , dann S 9 = S 1 × S 8S1,S2,S3,S4,…,S9 S1,S2,S4,S8,S9 S2=S1⊗S1 S4=S2⊗S2 S8=S4⊗S4 S9=S1×S8 . Finden Sie dabei das erste so dass 1 ∈ S k . Sobald Sie k so gefunden haben, dass 1 ∈ S k ist , können Sie sofort aufhören: Sie können die kleinste Teilmenge finden, deren gcd 1 ist, indem Sie sich die mit 1 verknüpfte Teilmenge ansehen . Sie können also anhalten, sobald Sie eine Menge S k erreichen, so dass 1 ∈ S k , wodurch Sie vorzeitig anhalten können, wenn Sie eine kleinere Teilmenge finden.k∈[1,2,4,8,9] 1∈Sk k 1∈Sk 1 1 Sk 1∈Sk
quelle
quelle
Wenn Sie eine Teilmenge mit gcd (S) = 1 finden können, kann ich immer redundante Elemente aus der Teilmenge entfernen, bis nur noch 2 Elemente übrig sind, die gcd (S) = 1 haben. Daher kann ich behaupten, dass entweder die kleinste Die Teilmenge enthält 2 Elemente oder ist nicht vorhanden.
Jetzt verwenden wir die Rekursion, um dieses Problem zu lösen. Teilen wir das Zahlenfeld in zwei Teile, einen mit n-1 Elementen und einen mit 1 Element (letztes Element). Entweder befinden sich die 2 Zahlen in den ersten n-1 Elementen oder ein Element aus dem ersten Teil, gepaart mit dem letzten Element. Daher können wir dieses Problem in lösen
T (n) = T (n-1) + O (n) Zeit. was bedeutet, T (n) = O (n ^ 2).
quelle