タイトルの答えを教えてください! 回答の方よろしくお願いします!
コードはこんなかんじで書きました!
ですが、答えが出てきません。
def divisor_sum(num, limit)
(1..limit).select{ |i| num % i == 0 }.sum
end
puts divisor_sum(1234567890, 50000000)
-
クリップを取り消します
-
質問の評価を上げたことを取り消します
-
質問の評価を下げたことを取り消します
+3
5000000以下のもの
puts divisor_sum(1234567890, 50000000)
桁を間違えています。Rubyではアンダースコア _ を挿入しても数値リテラルとして認識してくれるので、記述ミスを減らせます。
# 5,000,000以下のもの
puts divisor_sum(1_234_567_890, 5_000_000)投稿
score 5730
+1
残念ながら、ここではコード作成依頼は受け付けておりません。
まずはあなたなりにコードを書いてみましょう。
そのうえで、わからないことがあればそのコードとともに聞いていただければお答えできるかと思います
投稿
+1
アルゴリズムの改善案出しときますわ。
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で書いたで。
const divisor_sum = (num, limit) => {
let sum = 0; // 求める合計値
const sqrtNum = Math.sqrt(num); // num の平方根
for (let d = 1; d <= limit; ++ d) {
if (d > sqrtNum) // dがnumの平方根を超えたらループから抜ける
break;
if (num % d === 0) { // d が num の約数である
sum += d; // sum にdを加算
const q = num / d; // sum を d で割った商を求める(整数になる)
if (q <= limit && q !== d) { // qがlimit以下であり、かつ qとdが等しくない場合
sum += q; // 商qもsumに加算
}
}
}
return sum;
}
// テスト実行
console.log(divisor_sum(60, 18)); // => 58 (約数かどうかを調べるのは、7までで済む)
console.log(divisor_sum(1234567890, 5000000)); // => 1734174 (約数かどうかを調べるのは、35136までで済む)
console.log(divisor_sum(100, 30)); // => 67 (約数かどうかを調べるのは、10までで済む。100は10の2乗なので、10を2回足さないようにする。)
console.log(divisor_sum(60, 5)); // => 15 (この場合は、5は√60より小さいので、1以上5以下の全ての整数について60の約数かどうかを調べる)
➡ サンプル
一応、上のコードで // テスト実行 したテストケースは、質問にあるRubyの def divisor_sum(num, limit) でもやってみて、結果が一致したことは確認済みや。
ほなまた〜
投稿
score 221
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 87.69%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼