タイトルの答えを教えてください! 回答の方よろしくお願いします!
コードはこんなかんじで書きました!
ですが、答えが出てきません。
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%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼