元の問題としては
パズ懇神戸さん作の2015年の年賀問題
27で割り切れる最小の01十進数を求めよ
2015で割り切れる最小の01十進数を求めよ
というもの。
「01十進数」は0と1だけでできた十進数。
いわいはこれをC#のBigIntegerを使ったプログラムを書いて解いた。所要時間は短め。これはこれでめでたし。
そのプログラムを使って、27や2015だけでなく10000まで調べてみたら、
2439のときが解けなかった。理由はプログラムの作りが悪く、そして、探索が深すぎるためのメモリーオーバーフロー。
「この件」をパズル懇話会のMLで投稿したところ、パズ懇メンバー白川さんが、以下のようなプログラムを示してくれた。
>白川です。
>
>2439の時、解いてみました。
>
> 2439 * 00004100496519520340344449
> = 10001111011110110100111111
そのコードは参照してもらうとそれでよろしい。
のだが、蛇足ながら、説明w
①大筋
かける数を下の桁から決定していく。
例えば、2439の場合であれば、
下一桁目は 9*0=0 か 9*9=81 で0と1しかない。
掛け算の筆算的に書いて
■■■■■2439
×■GFEDCBA
---------
ABCDEFG・・・に当てはまる数を決定していく。ただし、ABC・・・それぞれに、候補が複数ある場合があるのでそれを探索していっている。
Aが9だとすると
■■■■■2439
×■■■■■■B9
---------
■■■■21951
1の位はOK。Bに関しては
2439×B+2195=の下一桁が0か1になるようなBをとる
この2195を白川プログラムではnextnumとしている。
Bを4と決めると
■■■■■2439
×■■■■■C49
---------
■■■119511
nextnum=1195 となる。
②プログラムの理解
tableが探索のための配列で、かつ記録をとる。
1桁解決した場合に未解決のnextnumが残り。
usedtableでnextnumの既出をチェック。(循環をふせぎ)
nextnumが1のときが終了条件で。(101とかも結局1にいきつくし、最小狙いでやるためには、これじゃないとだめ)
prevを記録しているので、復元できると。
もしも、答えがないときは、出力せずに終了。
③大局的な理解
nextnumを導入したところで、
問題が「分岐のある道の出口までの最短経路探索」になって。
最短経路=最小桁数ということ。
以上