PriorityQueueを使えば簡単です。まず、2からはじまる最長の素数列を求めます。そして、(列の長さ, 最初の素数のインデックス, 列の和)というタプルをPriorityQueueに入れます。PriorityQueueから要素を取り出して、今までの最長の素数未満の長さならそこで終わりです。そうでなくそれが素数なら最長を更新します。素数でなければはじまりは同じで一つ短い列をPriorityQueueに入れます。その列がその素数からはじまって最長の列なら、次の素数からはじまる最長の列もPriorityQueueに入れます。
10億まででも一瞬です。
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.PriorityQueue object Primes { private val primes = new ArrayBuffer[Int] private val L = 1e5.toInt private var offs = 0 def apply(n :Int) = { if(n >= primes.size) sieve primes(n) } private def sieve() = { if(offs == 0) sieve_1st else sieve_2nd_or_later offs += L } private def sieve_1st() = { val a = new Array[Boolean](L) for(i <- 2 to (L - 1)) a(i) = true for(p <- 2 to (L - 1) if a(p); m <- (p * 2) to (L - 1) by p) a(m) = false primes ++= (2 to (L - 1)).filter(a(_)).toArray } private def sieve_2nd_or_later() = { val N = offs + L - 1 val a = new Array[Boolean](L) for(i <- 0 to (L - 1)) a(i) = true for(p <- primes.takeWhile(p => p * p <= N); m <- ((offs + p - 1) / p * p) to N by p) a(m - offs) = false primes ++= (offs to N).filter(k => a(k - offs)).toArray } } def is_prime(n :Int) = Iterator.from(0).map(k => Primes(k)).takeWhile(p => p * p <= n). forall(p => n % p != 0) type Queue = (Int,Int,Int) // (列の長さ, 最初の素数のインデックス, 列の和) // (長さ, 和, 素数か) class gen_queue extends Iterator[(Int,Int,Boolean)] { val o = Ordering[Long].on[Queue](_._1) val pq = new PriorityQueue[Queue]()(o) init def hasNext() = true def next() = { val (l0, k0, s0) = pq.dequeue val b = is_prime(s0) if(!b && l0 > k0) pq.enqueue((l0 - 1, k0, s0 - Primes(l0 - k0 - 1))) if(s0 + Primes(k0 + l0) >= N) { // その素数から始まって最長の列 val s1 = s0 - Primes(k0) + Primes(k0 + l0) // 同じ長さの和 if(s1 < N) // 2, 3, 5, 7 -> 3, 5, 7, 11 pq.enqueue((l0, k0 + 1, s1)) else // 2, 3, 5, 7 -> 3, 5, 7 pq.enqueue((l0 - 1, k0 + 1, s0 - Primes(k0))) } (l0, s0, b) } def init() = { // (和, 最大のインデックス) val (s0, k0) = Iterator.iterate((0, -1))(s => (s._1 + Primes(s._2 + 1), s._2 + 1)). dropWhile(_._1 < N).next pq.enqueue((k0, 0, s0 - Primes(k0))) } } val N = 1e6.toInt val it = new gen_queue println (Iterator.iterate((0, 0)){x => val (l0, s0) = x val (l, s, b) = it.next if(b) if(l == l0) (l, s.max(s0)) else if(l > l0) (l, s) else (-1, s0) else if(l >= l0) (l0, s0) else (-1, s0) }.dropWhile(x => x._1 != -1).map(x => x._2).next)