Je souhaite effectuer une factorisation prime rapide avec Ruby (ABC177E)

référence

https://atcoder.jp/contests/abc177/editorial/82 (Je pense que l'article n'a pas de sens jusqu'à ce que vous lisiez ceci)

Sujet principal

Étant donné un grand nombre de nombres inférieurs ou égaux à A, lorsque vous voulez les factoriser en facteurs premiers Tamisez les Eratostènes et ajoutez le nombre qui a été tamisé. Facilité de factorisation prime

cache = {key(Sa valeur) => value(Le plus petit facteur premier qui a éliminé la clé) }

C'est une histoire qu'il est facile de faire un cache comme celui-ci.

Exemple) Lors de la factorisation de 100 en facteurs premiers

cache[100] 
#=> 2 =Diviser par 2
cache[100/2]
#=> 2 =Diviser par 2
cache[50/2] 
#=> 5 =Diviser par 5
cache[25/5] 
#=> 5 =Diviser par 5

#∴ 100 est divisé par 2 deux fois et 5 deux fois

Si vous créez ce cache, vous pouvez effectuer une factorisation première avec O (logN). Cette fois, j'ai essayé de créer une classe qui peut accélérer la factorisation prime en utilisant ceci, donc Je voudrais comparer les performances avec le [Integer # prime_division] existant (https://docs.ruby-lang.org/ja/latest/method/Integer/i/prime_division.html).

Ce que j'ai fait

https://github.com/k-karen/ruby-samples/blob/master/sieve/prime_div_with_sieve.rb

<détails> <résumé> Code source </ résumé>

#Je veux énumérer les nombres premiers avec un tamis Elatostines et effectuer une factorisation premier à grande vitesse!
# ref: https://atcoder.jp/contests/abc177/editorial/82
class PrimeDivWithSieve
  def initialize(n)
    @sieve = [] #Entrez des nombres premiers jusqu'à n
    @min_div = {} #Entrez le facteur premier minimum de la valeur de clé
    #Le nombre premier qui peut être éliminé peut aller jusqu'à sqrt
    (2..Math.sqrt(n).floor).each do |i|
      next if @min_div[i] #Il y a une valeur ici=Ont été éliminés
      @sieve << i #Si tu viens sans être tamisé, c'est un nombre premier

      sieve_target = i * i
      while sieve_target <= n do
        @min_div[sieve_target] ||= i
        sieve_target += i
      end
    end
    (Math.sqrt(n).floor.next..n).each do |i|
      next if @min_div[i]
      @sieve << i
    end
  end

  # Integer#prime_Essayez de renvoyer la même valeur que la division
  # https://docs.ruby-lang.org/ja/latest/method/Integer/i/prime_division.html
  def prime_division(num)
    return [[num, 1]] if !@min_div[num] #Renvoie immédiatement lorsqu'il s'agit d'un nombre premier

    return_array = [] # [[a, x], [b, y]] <=> num = a^x * b^y
    while num > 1 do
      prime = @min_div[num] #Facteur premier minimum, nil =>num est un nombre premier
      break return_array.push([num, 1]) if !prime

      div_total = 0
      while num % prime == 0 do
        num /= prime
        div_total += 1
      end
      return_array.push([prime, div_total])
    end

    return_array
  end

  def prime_list
    @sieve
  end
end

Comparaison des performances

(Code de test complet) [https://github.com/k-karen/ruby-samples/blob/master/sieve/bench_prime_division.rb]

N = 1_000_000
times = N/25 #Nombre de tests
TESTCASES = (1..N).to_a.sample(times)
require 'prime'

ans1 = []
ans2 = []
Benchmark.bm 10 do |r|
  r.report 'MyDivsor' do
    divisor = PrimeDivWithSieve.new(N)
    TESTCASES.each do |i|
      ans1.push(divisor.prime_division(i))
    end
  end

  r.report 'PrimeDiv' do
    TESTCASES.each do |i|
      ans2.push(i.prime_division)
    end
  end
end
# times = N/25 (40,000)
# Result
# user     system      total        real
# MyDivsor     0.875262   0.032392   0.907654 (  0.926605)
# PrimeDiv     0.849263   0.012468   0.861731 (  0.879886)

# times = N/2 (500,000)
# Result
# user     system      total        real
# MyDivsor     1.659268   0.058786   1.718054 (  1.758668)
# PrimeDiv    10.787444   0.118755  10.906199 ( 11.071594)

C'est subtil si le nombre de caisses est petit, mais il semble qu'il soit plus rapide d'utiliser le tamis à mesure que le nombre de caisses augmente.

ABC177E

https://atcoder.jp/contests/abc177/submissions/16390851 Je l'ai soumis parce que je pensais gagner, mais un TLE n'a jamais disparu. Je n'ai pas besoin d'informations sur le nombre de fois où il se cassera cette fois, alors Il a été décidé que je devrais prendre note des facteurs premiers de la valeur lors de la fabrication d'un tamis. Exemple) 100 => [2,5], 99 => [3, 11]

https://atcoder.jp/contests/abc177/submissions/16391235 Je suis passé par là. (C'est différent de la factorisation prime haute vitesse cette fois, alors veuillez l'utiliser comme bonus)

Calculez le facteur premier de chaque valeur jusqu'à n (avec tamis) https://github.com/k-karen/ruby-samples/blob/master/sieve/enum_elments.rb

<détails>

Code source </ summary>

#Calculer uniquement les facteurs premiers jusqu'à n
class EnumElements
  def initialize(n)
    @sieve = []
    @elements = {}
    (2..n).each do |i|
      next if @elements[i]
      @sieve << i
      @elements[i] = [i]

      sieve_target = i * 2
      while sieve_target <= n do
        if @elements[sieve_target]
          @elements[sieve_target].push(i)
        else
          @elements[sieve_target] = [i]
        end
        sieve_target += i
      end
    end
  end

  def elements(num)
    @elements[num] || []
  end
end

Recommended Posts

Je souhaite effectuer une factorisation prime rapide avec Ruby (ABC177E)
Je veux obtenir la valeur en Ruby
Je veux créer un fichier Parquet même en Ruby
[Java] Je veux effectuer distinctement avec la clé dans l'objet
Je veux changer la valeur de l'attribut dans Selenium of Ruby
Je veux utiliser @Autowired dans Servlet
[Ruby] Je souhaite afficher uniquement le caractère impair dans la chaîne de caractères
[Ruby] Je souhaite afficher les éléments publiés par ordre de date la plus récente
Je veux trier par délimiteur d'onglet avec ruby
[Ruby] Je veux faire un saut de méthode!
Je souhaite transmettre APP_HOME pour me connecter à Gradle
rsync4j --Je veux toucher rsync en Java.
Je veux être finalement même à kotlin
J'ai écrit un programme de factorisation prime en Java
Je souhaite effectuer un traitement d'agrégation avec spring-batch
Je souhaite également utiliser Combine dans UIKit.
Je souhaite utiliser les fonctions pratiques de Clojure dans Kotlin
Je veux aussi utiliser des coquillages à Laradock! !!
Je veux aussi utiliser ES2015 avec Java! → (´ ・ ω ・ `)
Je veux utiliser une petite icône dans Rails
Je souhaite définir une fonction dans la console Rails
Je veux arrêter les cas de serpent avec des définitions de table
Je veux cliquer sur une broche GoogleMap dans RSpec
Je veux trouver un chemin relatif dans une situation où Path est utilisé
Je veux convertir des caractères ...
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
Je souhaite passer au même écran dans l'état enregistré
[Ruby] Je souhaite inverser l'ordre de la table de hachage
Je souhaite simplifier l'instruction if-else de la branche conditionnelle en Java
[Wire Mock] Je souhaite configurer un serveur stub / simulé en Java et effectuer des tests E2E.
Webpack et webpacker que je veux dire aux gens de Ruby maintenant
Je souhaite ajouter une fonction de navigation avec ruby on rails
J'ai essayé d'écrire du code comme une déclaration de type en Ruby
Je veux obtenir des propriétés sous forme de chaînes JSON dans Jackson!
Je veux ajouter un appareil dans Rails, mais je ne peux pas grouper l'installation
Je veux supprimer la marge supérieure dans UITableView de Grouped (swift)
J'ai essayé de faire un Numeron qui n'est pas bon avec Ruby
Je souhaite effectuer un traitement asynchrone et une exécution périodique avec Rail !!!
[Android] Je souhaite obtenir l'auditeur à partir du bouton de ListView
Comment itérer indéfiniment en Ruby
Essayez d'implémenter Yuma dans Ruby
Comment installer Bootstrap dans Ruby
J'ai essayé de créer une classe parent d'objet de valeur dans Ruby
[Rails] Je souhaite envoyer des données de différents modèles dans un formulaire
Je veux écrire une JSP dans Emacs plus facilement que la valeur par défaut.
Je souhaite sélectionner plusieurs éléments avec une disposition personnalisée dans la boîte de dialogue
(Limité à Java 7 ou version ultérieure) Je souhaite que vous compariez des objets dans Objects.equals
[Ruby] Je souhaite extraire uniquement la valeur du hachage et uniquement la clé
[Note] Je veux obtenir dans l'ordre inverse en utilisant afterLast avec JdbcTemplate
J'ai essayé de résoudre le problème de la séquence Tribonacci en Ruby, avec récurrence.