これはグラフにすると比較的考えやすいです。例にあるように8128は三角数ですが、81という点と28という点が線で結ばれていて重みが3と考えます。ネットワークですね。4桁の3〜8角数を全て求めてネットワークを作ります。
そうしたときに、ある点から2の重み乗をビットごとのORを取りながらネットワークを辿って行きます。重複無しに3〜8の全てのフラグが立った0X1F8になって、しかも元の点に戻っていたらそれが解です。
import scala.collection.mutable.Map type Net = Map[Int,List[(Int,Int)]] def add_edge(g :Net, v1 :Int, v2 :Int, w :Int) = if(g.contains(v1)) g(v1) = (v2, w) :: g(v1) else g(v1) = List((v2, w)) def polygonal(p :Int)(n :Int) = n * ((p - 2) * n - p + 4) / 2 def make_graph() = { val g = Map[Int,List[(Int,Int)]]() for(p <- 3 to 8; f = polygonal(p :Int)_; n <- Iterator.from(1).map(f).dropWhile(1000 >).takeWhile(10000 >); upper = n / 100; lower = n % 100) add_edge(g, upper, lower, p) g } def find_loop(g :Net, v0 :Int) :List[Int] = { def step(v :Int, flag :Int) :List[List[Int]] = if(flag == 0x1F8) if(v == v0) List(Nil) else Nil else if(!g.contains(v)) Nil else for((n, p) <- g(v) if (flag & (1 << p)) == 0; vs <- step(n, flag | (1 << p))) yield n :: vs step(v0, 0).map(vs => vs.sum * 101) } val g = make_graph() println (g.keys.flatMap(v0 => find_loop(g, v0)))