タイトルの答えを教えてください! 回答の方よろしくお願いします!
コードはこんなかんじで書きました!
ですが、答えが出てきません。
def divisor_sum(num, limit)
(1..limit).select{ |i| num % i == 0 }.sum
end
puts divisor_sum(1234567890, 50000000)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/30 06:34
2021/08/30 07:02
2021/08/30 07:35
回答3件
0
アルゴリズムの改善案出しときますわ。
1以上limit
以下のすべての整数について、num
の約数かを調べる必要が常にあるか?といったら無いねんな。題意の和を計算するためには、1以上かつmin { √num を超えない最大の整数, limit }
以下の整数について、num
を割り切るか調べれば十分ですわ。
たとえば、質問にあるように num
が 1234567890 で、limit
が 5000000 のとき、√num を超えない最大の整数
は、35136 で、これは 5000000 よりも(かなり)小さく、num
を割り切るかどうかのチェックは、1以上35136以下の数に対してだけやれば済むこっちゃ。
以下、考え方の説明します。話を簡単にするため、例えば、num
が60、limit
が18としますわ。
-
60を割りきるか調べる数(1以上18以下の整数)を変数
d
とします。 -
また、求める合計を
sum
とします。sum
の初期値はゼロです。 -
まず、
d
が 1 のとき、60を割り切るので、sum
に 1 を加えます。 -
このとき、つまり、
num
をd
が割り切るとき、num ÷ d
の商q
もnum
の約数やねんな。num
が60でd
が1のときは、商q
は60で、60は18以下ではないので、この場合はsum
には足しませんが、もし商q
が 18 以下になっていれば、商もsum
に加えます。 -
d
を、1から順に1つずつ増やして、上記の操作をやっていくと、d
が4のとき、q
が15になり、初めて商のほうも18以下になりsum
に加えることになる。 -
引き続き、
d
が 5および6のとき、d
自身とともに、それらで割った商q
として得られる 12および10 も (18以下なので)sum
に加えます。 -
このような操作によって
sum
に累積していくとき、d
の上限としては、√60 (60の平方根: 7.74...)を超えない最大の整数である7まで調べればよい。(なぜなら、8以上の整数でsum
に加算すべきものは、それまでのループの中で、既に商q
として出現しており、その中でlimit
以下のものはsum
に加算済みだから。) -
ただし、
num
が平方数の場合、たとえば100のとき、√100 は 10なので、d
が 10 のとき、商q
も 10 になり、limit
がたとえば20のとき、上記の操作だと10を2回sum
に足してしまうことになるので、重複して足さないようなロジック追加が必要
以上を実装した divisor_sum()
のコード例が以下です。ワテ、Rubyは得意やないもんで、javascriptで書いたで。
javascript
1const divisor_sum = (num, limit) => { 2 3 let sum = 0; // 求める合計値 4 const sqrtNum = Math.sqrt(num); // num の平方根 5 6 for (let d = 1; d <= limit; ++ d) { 7 8 if (d > sqrtNum) // dがnumの平方根を超えたらループから抜ける 9 break; 10 11 if (num % d === 0) { // d が num の約数である 12 sum += d; // sum にdを加算 13 const q = num / d; // sum を d で割った商を求める(整数になる) 14 if (q <= limit && q !== d) { // qがlimit以下であり、かつ qとdが等しくない場合 15 sum += q; // 商qもsumに加算 16 } 17 } 18 } 19 20 return sum; 21} 22 23 24// テスト実行 25console.log(divisor_sum(60, 18)); // => 58 (約数かどうかを調べるのは、7までで済む) 26console.log(divisor_sum(1234567890, 5000000)); // => 1734174 (約数かどうかを調べるのは、35136までで済む) 27console.log(divisor_sum(100, 30)); // => 67 (約数かどうかを調べるのは、10までで済む。100は10の2乗なので、10を2回足さないようにする。) 28console.log(divisor_sum(60, 5)); // => 15 (この場合は、5は√60より小さいので、1以上5以下の全ての整数について60の約数かどうかを調べる)
➡ サンプル
一応、上のコードで // テスト実行
したテストケースは、質問にあるRubyの def divisor_sum(num, limit)
でもやってみて、結果が一致したことは確認済みや。
ほなまた〜
投稿2021/08/30 12:59
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/30 15:59
2021/08/31 01:15
2021/08/31 01:35
2021/08/31 01:36
退会済みユーザー
2021/09/01 01:42
2021/09/01 02:08 編集
0
残念ながら、ここではコード作成依頼は受け付けておりません。
まずはあなたなりにコードを書いてみましょう。
そのうえで、わからないことがあればそのコードとともに聞いていただければお答えできるかと思います
投稿2021/08/30 06:22
総合スコア88024
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。