$30 off During Our Annual Pro Sale. View Details »

Project Eulerの話

nozma
April 05, 2019

Project Eulerの話

Project Eulerについて紹介しました。

nozma

April 05, 2019
Tweet

More Decks by nozma

Other Decks in Programming

Transcript

  1. Project Euler の話 @nozma 2019-04-05

  2. 最近AtCoder はじめました まだクソザコナメクジ。 2 / 40

  3. 実は深刻な問題があります 3 / 40

  4. R が使えない… 4 / 40

  5. R が使えない…!! 5 / 40

  6. R を!!!!!!!!!! 使わせろ!!!!!!! 6 / 40

  7. プロコンあるある Rが使えない(重要) バージョンが古い 好きなライブラリを使えない Rが使えない(重要) 仕方ないのでC++で解いてます 7 / 40

  8. Project Euler そんな私に 8 / 40

  9. 論文を沢山書いたおじさんです。 誰? 9 / 40

  10. 何? 数学の問題集です。 コンピュータを用いて計算することが想定されています。 10 / 40

  11. Project Euler のここがすごい ルールが簡単 n桁の数字を解答欄に書き込むだけ(n=チョット) 時間に制限がない 1分以内に解けるように設計されている(one-minute rule) ググっても良い むしろ推奨されている

    11 / 40
  12. Project Euler のここがすごい (たまに)解説PDFがある (実際あんまりない) フォーラムがある 時間をかけて解く -> フォーラムで賢いやり方を学ぶというのが一般的 言語に制限がない

    手元で実行なので当然 12 / 40
  13. 言語に制限がない!!! 13 / 40

  14. どんな言語が使われているのか? AtCoderとProject Eulerでそれぞれ集計してみました。 14 / 40

  15. AtCoder のランキング APIがあったのでそこからデータ取得 kenkoooo/AtCoderProblems: Problem manager for AtCoder users jsonをrlistパッケージで読み込んで加工

    次の項目を計算してグラフを作成 ユーザー数 ... ACが1件以上あればユーザとカウント AC平均 ... Accepted合計 / ユーザー数 15 / 40
  16. AtCoderの使用言語ランキング 16 / 40

  17. AtCoderのつよい言語ランキング 17 / 40

  18. Project Euler のランキング Statistics - Project Eulerに統計情報があるので取得 認証が必要なのでRSelenium パッケージでログイン rvestでスクレイピング

    次の情報があるので可視化(件数が多いので上位50%のみ) ユーザー数...ユーザーがプロフィールで設定するもの 回答率...回答数/問題数が言語別に集計されたもの 18 / 40
  19. Project Eulerの使用言語ランキング 19 / 40

  20. つよい言語ランキング 20 / 40

  21. やってみよう 21 / 40

  22. Problem 1 -- Multiples of 3 and 5 3か5で割り切れる1000未満の自然数の合計は何か? PE版のfizzbuzzです。

    22 / 40
  23. PE001 回答例 23 / 40

  24. 素直に解く ans 0 for (i in seq_len(999)) { if (i

    3 0 | i 5 0) { ans ans + i } } 良いと思います。 24 / 40
  25. もっとFizzBuzz っぽく sum((x=1:999)[!(x 3&x 5)]) 書き方にこだわってみても良いでしょう。 25 / 40

  26. もっと最近のR っぽく library(dplyr) data.frame(x = 1:999) %>% filter(x 3 0

    | x 5 0) %>% summarise(answer = sum(x)) 好きなライブラリを使ったって良いんです。 26 / 40
  27. Python が使いたいんじゃ print(sum(i for i in range(1000) if i %

    3 0 or i % 5 0)) どうしてもPythonが良いというなら止めません。 27 / 40
  28. あまり役に立たない知見が得られる問題が盛りだくさんです 28 / 40

  29. Problem 92 Square digit chains 「各桁の値の2乗の合計を計算する」という操作を繰返します。 44 -> 32 ->

    13 -> 10 -> 1 -> 1 85 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16 -> 37 -> 58 -> 89 1つめの例では、1に到達し、2つめの例では89から始まるループに到達しています。実 は、操作を繰り返すとすべての自然数は1または89に到達します。 1千万以下の自然数のうち、89に到達する数はいくつあるでしょうか? 29 / 40
  30. 考え方 上限をN、ループ判定に必要な時間をMとして 程度の計算量が 必要です。 N = 1e7なので、Mの値次第では結構時間がかかります。 どうするか?(考えてみましょう) ヒント:ほぼ の解法があります

    O(N × M ) O(N ) 30 / 40
  31. 回答例 「2乗の和」の計算結果は、最大でも です すべての値について1回だけ処理をすれば、すべて486以下の値になりま す。 したがって486以下の整数について最終的に89になるのか?を把握してお き、配列などにメモっておけば高速に計算できます。 9 2 ∗

    6 = 486 31 / 40
  32. Project Euler のここがすごい 日常生活で比較的使わない概念を知ることができます 32 / 40

  33. Q. 何? 3 ⇈ 3 33 / 40

  34. 答: テトレーション cf. 大きな数が好きなら寿司 虚空編を読もう! 3 ⇈ 3 = 3

    3 3 = 3 27 = 7, 625, 597, 484, 987 34 / 40
  35. Problem 188 の下8桁を求めよ。 ヒント1: 桁だけでメモリが死ぬので直接計算してはいけません ヒント2: 冪乗演算子は右結合なので左から計算してはいけません # n 1777

    for (i in 1:1855) n n^1777 mod 1e8 1777 ⇈ 1855 35 / 40
  36. オイラーの定理 と を互いに素な正整数とします。このとき次の関係が成立します。 はオイラーの (トーシェント)関数というもので、 以下の自然数で と互いに素な自然数の個数を返します。 例) なら1と5が互いに素なので 。

    とすると、 となってオイラーの定理が成り立つ。 a n a φ(n) mod n = 1 φ(n) φ n n n = 6 φ(6) = 2 a = 5 5 2 mod 6 = 1 36 / 40
  37. で? 1777は素数なので、1e8と互いに素です。つまり次の関係が成り立ちます。 乗する度に下8桁が00000001に戻るということです。つま りこうです。 指数部分の剰余をとってから計算して良いということです。 1777 φ(10 8 ) mod

    10 8 = 1 φ(10 8 ) = 4 × 10 7 1777 x mod 10 8 = 1777 x mod 4×10 7 mod 10 8 37 / 40
  38. コードにするとこう solve function(a, b, m) { ans = 1 for

    (i in seq_len(b)) { if (i b) m = 1e8 ans = modpow(a, ans, m) } return(ans) } solve(1777, 1855, 4e7) ※冪乗の剰余を計算する関数がRには無いので適当に定義する必要がありま す。メンドイ!! 38 / 40
  39. 実は… ループは10回で良い で剰余とっても良い Pythonだと楽 x = 1 for i in

    range(10): x = pow(1777, x, 10 8) print(x) とかいろいろあって闇が奥が深いです。問題解いてからforum覗いてみるとよ いでしょう。 10 8 39 / 40
  40. 終 40 / 40