###追記
解決したのは数ヶ月前でしたが別言語で改めて実装してみたところ
@swordoneさんの回答に近い実装で今のところ最速となりました。
当時はまだ理解が足りていなかったのでBAを変更させていただきました。
要点としては・・・
1.約数の個数は素因数分解で求める
2.1つ前で求めた解をキャッシュして使う ※@swordoneさんコードのlow,high変数
約数の個数と素因数分解の参考情報
約数の個数の公式と平方数の性質
素因数分解と約数の個数と総和の求め方を説明!|数学勉強法
結果が出るまで時間が掛かり過ぎる
参考にした例題元 リンクURL
結果が出るまで10分以上掛かり何度も中断しているので改善点などアドバイス頂けたら幸いです。
※ソースコードは結果が即出るように変数を設定しています。
ソースコード
java
1 /** 2 * 3 * 問題 https://projecteuler.net/problem=12 4 * ※以下Google翻訳 5 * 三角数のシーケンスは、自然数を加算することによって生成されます。 6 * したがって、7 番目の三角形の数は1 + 2 + 3 + 4 + 5 + 6 + 7 = 28となります。 7 * 最初の10の項は次のようになります。1、3、6、10、15、21、28、36、45、55、... 8 * 最初の7つの三角数の要素をリストアップしましょう。 9 * 10 * 1:1 11 * 3:1,3 12 * 6:1,2,3,6 13 * 10:1,2,5,10 14 * 15:1,3,5,15 15 * 21:1,3,7,21 16 * 28:1,2,4,7,14,28 17 * 18 * 28が5つの除数を持つ最初の三角形の数であることが分かります。 19 * 最初の三角形の数には何百もの約数がありますか? 20 * 21 * 原文:What is the value of the first triangle number to have over five hundred divisors? 22 * 23 * ---以下推測--- 24 * 25 * 28: 1,2,4,7,14,28 26 * 2,4,7,14,28 ===>>> 5 27 * 28 * over five hundred divisors? 29 * 約数が500以上の三角数を求める? 30 * 31 */ 32 public static void main(String[] args) { 33 34 long start = System.currentTimeMillis(); 35 36// func(5, 1); //0ms //Answer:28 37// func(300, 1); //2245ms //Answer:2162160 38 func(500,12375); //205ms //Answer:76576500//即答用 39// func(500,1); //未達 40 41 long end = System.currentTimeMillis(); 42 System.out.println((end - start) + "ms"); 43 System.out.println(); 44 45 }
java
1 /** 2 * num個以上の約数を持つ最初の三角数を求める 3 * @param num : 約数の数 4 * @param cnt : 探索開始初期値1 5 */ 6 static void func(int num, int cnt) { 7 8 //探索開始初期値 9 int counter = cnt; 10 // 即答用 11 // int counter = 12375; 12 // ログ c:12375 t:76576500 d:575 13 // Answer:76576500 14 15 while (true) { 16 17 //三角数 18 int triangle = 1; 19 20 for (int i = 2; i <= counter; i++) { 21 triangle += i; 22 } 23 24 //奇数はスキップ 25 if (triangle % 2 == 1) { 26 counter++; 27 continue; 28 } 29 30 //約数 31 int divisors = 0; 32 33 for (int i = 2; i <= triangle; i++) { 34 if (triangle % i == 0) { 35 divisors++; 36 } 37 } 38 39 //ログ 40// System.out.println("Log c:" + counter + " t:" + triangle + " d:" + divisors); 41 42 //出力 43 if (divisors >= num) { 44 System.out.println("Answer:" + triangle); 45 return; 46 } 47 counter++; 48 } 49 }
出力結果(※即答用に変数を指定した場合)
Answer:76576500
204ms
試したこと
java
1 //奇数はスキップ 2 if(triangle % 2 == 1) { 3 counter++; 4 continue; 5 }
- 大きい解は偶数のみなので暫定的に奇数はスキップするようにしたところ300個探索で約2倍速度upしました。
counter
探索開始初期値を変更することで解を即答出来るようにしました。
わからないこと
- 例題なので答えがすぐに表示される解法があるのではないか
- ボトルネックになっているのはどこなのか
初歩的な総当たりループで探索し初期値を手動で変更などしているので本来の求め方では無いと思います。
指数倍的に時間が掛るのはループに原因があるのかなと思いますがアドバイスやヒントなど頂けましたら幸いです。
回答6件
あなたの回答
tips
プレビュー