Problem:
C : Mod!Mod!

物語

じゃん！探してますよ目撃証言！
会津に怪盗が現れた！みんなのウマウマ棒が盗まれた！犯人は誰だ！？
解きあかせ！Mod!Mod!

問題文

"アイズ"...それは選ばれし者の心に膨らむ奇跡のつぼみ...。特殊能力"アイズ"を使えばどんなものだって盗むことができる。

会津一の大怪盗、あいずまるは世界を謎で満たすためにn人の探偵から「ウマウマ棒」を盗むことにした。ウマウマ棒とはあいずまるが大好きなただのお菓子であり、n人の探偵はそれぞれ数本のウマウマ棒を持っている。また、あいずまるは強欲なためそれぞれの探偵からウマウマ棒を盗むとき、その探偵が所持する全てのウマウマ棒を盗む。

ウマウマ棒の3本同時食いにハマっているあいずまるは、3本以上のウマウマ棒が手元にあるとき、誘惑に負けて手持ちのウマウマ棒が3本未満になるまで、3本ずつウマウマ棒を食べてしまう。しかし、あいずまるは手元にウマウマ棒がないとショックでアイズを失ってしまい、それ以上ウマウマ棒を盗むことができなくなってしまう。つまり、ウマウマ棒を盗むためには手持ちのウマウマ棒の本数を1本以上にしておく必要があり、0本になるとそれ以上ウマウマ棒を盗むことができなくなる。

少しでも多くの探偵からウマウマ棒を盗みたいあいずまるは、どの探偵から順にウマウマ棒を盗むかによって何人の探偵からウマウマ棒を盗めるのかが変わることに気づいた。しかし、あいずまるには難しいことは分からない。「ハテー？」あいずまるの優秀な部下であるあなたは、あいずまるの代わりに最大で何人の探偵からウマウマ棒を盗むことができるのかを求めるプログラムを書いてあげることにした。

探偵の人数nと、n人の探偵からそれぞれ何本のウマウマ棒を盗むのかが与えられるので、最適な順番で探偵からウマウマ棒を盗んだとき、最大で何人の探偵からウマウマ棒を盗むことができるかを出力するプログラムを作成せよ。ただし、はじめの手持ちのウマウマ棒の本数は0であるが、最初に限り手持ちが0本でもウマウマ棒を盗むことができるとする。

入力形式

入力は2行からなり、以下の形式で与えられる。

n
a_1 a_2 … a_n

1行目には、ウマウマ棒を盗む探偵の数である整数nが与えられる。
2行目には、各探偵から盗むウマウマ棒の本数n個が空白区切りで与えられる。

制約

1 ≤ n ≤ 500{,}000

1 ≤ a_i ≤ 9 (1 ≤ i ≤ n)

出力形式

最適な順番で探偵からウマウマ棒を盗んだとき、最大で何人の探偵からウマウマ棒を盗むことができるか一行に出力せよ。

入力例1

6
2 5 2 5 2 1

出力例1

5

2 5 1 2 5の順で盗むと5人から盗むことができる。どのような順序で盗んでも6人から盗むことはできない。

入力例2

3
3 6 9

出力例2

1

どの1人から盗んでも手持ちのウマウマ棒の本数は0になってしまい、アイズを失ってしまう。

入力例3

6
1 2 3 4 5 6

出力例3

6

Solution in Scala (judge verdict: Accepted)

import scala.collection.mutable.Queue
import io.StdIn

object Main extends App {
  val n = StdIn.readInt
  val seq = StdIn.readLine.split(" ").map(_.toInt % 3)
  val a = for(i <- 0 until 3) yield seq.count(_ == i)

  def bfs(first:Tuple5[Int,Int,Int,Int,Int]):Int = {

    val que = new Queue[Tuple5[Int,Int,Int,Int,Int]]
    que += first
    var cur = (0,0,0,0,0)

    var isCnt = true
    while(isCnt || !que.isEmpty) {
      cur = que.dequeue

      if(cur._2 == 0 || (cur._3 == 0 && cur._4 == 0 && cur._5 == 0)) isCnt = false
      else {
        cur match {
          case (acc, 1, c0, c1, c2) if c0 != 0 => que += {(acc+1, 1, c0-1, c1, c2)}
          case (acc, 2, c0, c1, c2) if c0 != 0 => que += {(acc+1, 2, c0-1, c1, c2)}
          case (acc, 1, c0, c1, c2) if c1 != 0 => que += {(acc+1, 2, 0, c1-1, c2)}
          case (acc, 2, c0, c1, c2) if c2 != 0 => que += {(acc+1, 1, 0, c1, c2-1)}
          case (acc, 2, c0, c1, c2) if c1 != 0 => que += {(acc+1, 0, 0, c1-1, 0)}
          case (acc, 1, c0, c1, c2) if c2 != 0 => que += {(acc+1, 0, 0, 0, c2-1)}
        }
      }
    }
    cur._1
  }

  val res1 = if(a(1) == 0) 0 else bfs(0,1,a(0),a(1)-1,a(2)) + 1
  val res2 = if(a(2) == 0) 0 else bfs(0,2,a(0),a(1),a(2)-1) + 1
  val ans = if(a.drop(1).sum == 0) 1 else math.max(res1,res2)
  println(ans)
}