ABC177 - E in Ruby lösen

Einführung

Ich hatte die Gelegenheit, eine ausführliche Erklärung zu E-Problem von AtCoder Beginner Contest 177 zu schreiben. Es war besser als ich erwartet hatte, also werde ich es als Artikel zusammenfassen.

Erwägung

Unter Problem kann der Fokus in der folgenden Reihenfolge in drei Bereiche unterteilt werden.

  1. "GCD (A_i, A_j) = 1 für alle 1 ≤ i <j ≤ N" gilt.
  2. "GCD (A_1 ... A_N) = 1" gilt
  3. Weder gilt

Von nun an werden wir uns diese drei genauer ansehen.

1. "GCD (A_i, A_j) = 1 für alle 1 ≤ i <j ≤ N" gilt.

Fragen Sie in jedem Fall ehrlich.

N.times do |i|
  N.times do |j|
    if A[i].gcd(A[j]) != 1 then
      is_pairwise_coprime = false
    end
  end
end

Aufgrund der Einschränkung ist $ 2 ≤ N ≤ 10 ^ 6 $, sodass das Maximum $ O (10 ^ {12}) $ ist und das Ausführungszeitlimit von 2 Sekunden nicht eingehalten werden kann.

Achten Sie hier darauf, dass die maximale Verpflichtungszahl einer Kombination 1 beträgt. Dies bedeutet, dass jede Kombination von ganzen Zahlen $ (A_i, A_j) $ Primzahlen zueinander sind.

Daher werden alle N ganzen Zahlen in Primfaktoren zerlegt, und wenn dieselben Primfaktoren nicht auftreten, gilt dies, und es wird "paarweises Koprime" ausgegeben.

2. "GCD (A_1 ... A_N) = 1" gilt

Dies ist O (N), auch wenn es ehrlich gedreht wird, sodass kein Raum für Überlegungen besteht.

res = a[0]
a.each do |elm|
  res = res.gcd(elm)
end

Wenn 1 nicht hält und "res == 1", sollte "setwise coprime" ausgegeben werden. Und wenn keiner von 3. wahr ist, wird "nicht Coprime" ausgegeben.

Daraus ergibt sich 1 als Hauptüberlegung.

Primfaktorisierung

Ruby hat ein Prime-Modul, das aus Prime.prime_division berücksichtigt werden kann. Referenz: Spielen mit Primzahlen in Ruby (Primmodul)

Dies scheint leicht zu lösen zu sein. Einreichen! image.png

Nicht in der Zeit. Was sollen wir dann tun?

osa_k Methode

Es ist am schnellsten, einen Blick auf [Eratostenes 'Sieb und schnelle Primfaktorisierung] zu werfen (https://blog.manuel1024.com/archives/79), aber ich werde es auch hier auf meine eigene Weise erklären.

Dies ist ein Algorithmus, der positive ganze Zahlen kleiner oder gleich N (in diesem Fall $ A_ {max} $) in Primfaktoren zerlegt. Mach O (log M) $). Der Berechnungsbetrag beträgt $ O (log M) $ von $ O (log log N + log M) $. Ab diesem Maximalwert $ A_ {max} = 10 ^ 6 $ ist es ungefähr $ O (log 10 ^ 6) = O (10) $. Daher beträgt der Berechnungsaufwand zum Ermitteln der Primfaktoren aller N ganzen Zahlen ungefähr $ O (N log A_ {max}) = O (10 ^ 7) $, was ausreichend ist.

Zusammenfassend,

Ist ein Algorithmus

Vorverarbeitung

Finden Sie den minimalen Primfaktor min_factor für ganze Zahlen (1 ~ N) kleiner oder gleich $ N = A_ {max} $. Betrachten Sie bei der Anwendung des Erratostinesiebs mehrere k von i (= 2 ~ $ \ sqrt {N} $) in der angegebenen Reihenfolge. Wenn i kleiner als der in k enthaltene Wert ist, geben Sie i ein.

Beispiel: Nehmen wir zum Beispiel den Maximalwert N = 16 des Wertes, der in Primfaktoren berücksichtigt werden soll. Da $ \ sqrt {16} = 4 $ ist, beträgt der Bereich von i 2 ~ 4. image.png

Schauen Sie sich i der Reihe nach an und erstellen Sie ein Array min_factor, in dem die kleinsten Primfaktoren gespeichert sind.

image.png

Der letzte Teil ist die Sequenz min_factor.

Dieser Prozess

Bitte beachten Sie das folgende Flussdiagramm.

image.png

Das Ergebnis der Primfaktorisierung wird im Ergebnis gespeichert. Da dieselbe Primzahl mehrmals gespeichert wird, verwenden Sie "uniq" oder "set", wenn Sie nur Primfaktoren möchten.

Wenn das obige Beispiel auf den obigen Fluss angewendet wird, wird es wie in der folgenden Abbildung gezeigt.

image.png

Es sieht so aus, als könnten Sie damit Code in AC schreiben.

Implementierung

class Osa_k
    # @parm {number} n -Maximaler Wert unter den Werten, die Sie berücksichtigen möchten
    def initialize(n)
        @min_factor = [*0..n]
        i = 2
        while i * i <= n do
            if @min_factor[i] == i then
                j = 2
                while i * j <= n do
                    @min_factor[i*j] = i if @min_factor[i*j] > i
                    j += 1
                end
            end
            i += 1
        end
    end
 
    # @parm {number} m -Wert, den Sie berücksichtigen möchten
    # @return {array} res -Primfaktorgruppe von m
    def factor(m)
        res = []
        tmp = m
        while tmp > 1 do
            res << @min_factor[tmp]
            tmp /= @min_factor[tmp]
        end
        return res.uniq
    end
end
 
MAX = 10 ** 6 + 10 #Maximalwert ist 10^Weil es 6 ist
n = gets.chomp.to_i
a = gets.chomp.split.map(&:to_i)
osa_k = Osa_k.new(MAX)
res = a[0]
h = Hash.new(0) #Verwalten Sie mithilfe assoziativer Sequenzen, ob Primfaktoren bereits aufgetreten sind
is_pairwise_coprime = true #Ob die erste Bedingung erfüllt ist
n.times do |i|
    #Sie müssen es nicht tun, wenn Sie feststellen, dass die erste Bedingung nicht erfüllt ist
    if is_pairwise_coprime then
        osa_k.factor(a[i]).each do |num, cnt|
            if h.has_key?(num) then
                is_pairwise_coprime = false
                break
            end
            h[num] += 1
        end
    end
    res = res.gcd(a[i]) #Überprüfen Sie die zweite Bedingung
end
 
if is_pairwise_coprime then
    puts "pairwise coprime"
elsif res == 1 then
    puts "setwise coprime"
else
    puts "not coprime"
end

Übermittlungsergebnis: https://atcoder.jp/contests/abc177/submissions/16583524

abschließend

AC war dank Eratostenes-Sieb und schnelle Primfaktorisierung möglich. Ich möchte mich hier bei Ihnen bedanken.

Recommended Posts

ABC177 - E in Ruby lösen
Lösen mit Ruby, Perl und Java AtCoder ABC 113 C Referenz
Schwer in Rubin! ??
AtCoder ABC 169 C Gleitkomma, das in Ruby passt
Ausgabedreieck in Ruby
Arten von Variablen in Ruby
Schneller Popcount in Ruby
AtCoder ABC129 D 2D-Array In Ruby und Java gelöst
Lösen mit Ruby, Perl und Java AtCoder ABC 128 C.
Überprüfen Sie JWT-Token in Ruby
Integer # pow wird empfohlen, um die Quadratmethode in Ruby wiederholt zu lösen
Schreiben Sie die Klassenvererbung in Ruby
Aktualisieren Sie Ruby in der Unicorn-Umgebung
Ganzzahlen, die in Ruby 2.4 zu Ganzzahlen zusammengefasst sind
[Ruby] Ausnahmebehandlung in Funktionen
Verwenden Sie Ruby-Variablen in Javascript.
Multiplikation innerhalb eines Ruby-Arrays
Über reguläre Ausdrücke in Ruby
Lösen mit Ruby, Perl und Java AtCoder ABC 129 C (Teil 1)
NCk mod p in Ruby
AtCoder ABC 136 D Suche nach Breitenpriorität Gelöst in Ruby, Perl und Java
ABC - 134 - A & B & C & D & E.
Wie man in Ruby auf unbestimmte Zeit iteriert
Versuchen Sie, Yuma in Ruby zu implementieren
Erzielen Sie eine dreistellig begrenzte Anzeige in Ruby
Codierung unter Windows + Ruby
Ruby on Rails Japanisch-Englisch kompatibler i18n
So installieren Sie Bootstrap in Ruby
Implementieren Sie den gRPC-Client in Ruby
Schreiben Sie Schlüssel und Werte in Ruby
ABC - 131 - A & B & C & D & E.
[Super Einführung] Über Symbole in Ruby
Hanachan in Ruby (zerstörungsfreie Array-Manipulation)
OpenSL-Versionsinformationen in Ruby OPENSSL_VERSION
Ruby-Methoden, die häufig in Rails verwendet werden
Segfo Ruby in 2 Zeilen
AtCoder ABC 111 C Hash-Sortierung In Ruby, Perl und Java gelöst
Lösen mit Ruby, Perl und Java AtCoder ABC 129 C (Teil 2) Dynamische Planungsmethode