2019年4月9日火曜日

CS Academy Round #21 - 0-K Multiple

CS Academy Round #21 - 0-K Multiple

まずは全探索を考えることにする。例えばK=7K=7のとき、77077700707...7 \rightarrow 70 \rightarrow 77 \rightarrow 700 \rightarrow 707 \rightarrow ...のように昇順にNNの倍数かどうかチェックしたい。これはキューを使えば簡単に実現できる。整数iiをキューから取り出したら、10i10i10i+K10i+Kをキューに加えればよい。しかし、問題点が2つある:

  1. そもそも全探索は間に合わない
  2. 64ビット整数の範囲を容易に超えてしまう

1つ目の問題は、NNを法として合同な整数を2度は処理しないことで解決する。iji \equiv jなら10i10j10i \equiv 10j10i+K10j+K10i+K \equiv 10j+Kだから、代表元として最小のものだけ処理していけばよい。2つ目の問題は、キューに加える整数をmod  N\mod Nを取った整数とすれば解決できそうだが、そうすると元の整数がわからなくなってしまう。この制約では2進法で11011100101...1 \rightarrow 10 \rightarrow 11 \rightarrow 100 \rightarrow 101 \rightarrow ...のようにコーディングすれば64ビットに収まるので、これとペアでキューに加えれば良いようだ。しかし、上限の評価はそんなに明らかでもない。1 単方向リストで永続スタックを作る感じにしたほうが確実だと思った。


  1. 解説にある通り、高々NNビットで十分なのはすぐにわかるが…… ↩︎