午後のひとときに、今取り組んでいる数学の問題を紹介する。
問題
a 2 | + | b 3 | + | c 5 | + | d 7 | = | 1 abcd |
左辺の分母が素数で、分子が0ではない整数のとき、
右辺の分母の絶対値が最小となる組を求めよ。
という問題について、左辺の項数を増やしていくことを考えている。
前回の時点で10項までは何らかの解を見つけた。
項数 | 左辺分子 | 右辺分母の絶対値 |
2 | 1,-1 | 1 |
3 | -1, 1, 1 | 1 |
4 | 1, 1,-2,-3 | 6 |
5 | 1,-1,-2, 1, 1 | 2 |
6 | 1,-1, 1,-1,-5, 3 | 15 |
7 | -1, 1,-2, 2, 1, 4,-2 | 32 |
8 | -1, 1, 2,-1,-4, 5,-1, -1 | 40 |
9 | 1.-1,-1, 3,-4, 7,-3, -5, -3 | 3780 |
10 | -1, 1, 1, 3, 1,-2, 4,-10,-12,12 | 34560 |
ここまではどうにかこうにか求めたんだが、そこからは時間がかかりすぎる。
しばらく、大した策略もなく時間のかかるプログラムを回していたら、11項目の解を見つけた。
項数 | 左辺分子 | 右辺分母の絶対値 |
11 | -1, 1, 1, 1, 5,-3,-7,-4, 10, 6,-13 | 327600 |
さて、法則もなにも解らない状況は続いているが、プログラムの改善方法がおもろげにみえてきた。
この問題の性質上、ネストが多くなるのはどうにも出来ない。
しかし、何らかの解が見つかれば、右辺分母の絶対値の値より大きな値になるケースはバッサリと枝刈り出来る。
つまり、出来る限り早く何らかの解が見つけ出せることが重要なのではなかろうか?ということ。
今までのforループは、
for (a=-n; a<=n; a++)
のようなものをネストしていたが、これではnが大きくなると、0付近に来るのが遅くなってしまう。
そこで考えついたのが、
-1、1、-2、2、-3、3、…、-n、+n
のような変数の変化をするforループを考え、
for (a=-1, a1=2; a<=n; a+=a1, a1*=a/abs(a), a1*=-1)
というようなものに変更することにした。
これで少しは早くなんらかの解を見つけてくれるのだろうか。
もう一つ考えたのが、符号を一番内側に別のループで作るということ。
この場合は、
for (a=1; a<=n; a++)
で良いので、
符号用のネストを2進数で考えて、項数に応じて2進数の桁数を増やせばよい。
さて、どちらが答えを早く見つけてくれるかということになったが、12項の解が見つかったら、また何か考えようかな。