17. D問題 解法
? 閉路の長さをC、 閉路に到達するまでの長さをT とおき
ます。
? k が十分大きく、k 回移動したときに閉路に到達している
ものとします。
? このとき、k mod C (k を C で割った余り) さえ求まればOK
– 閉路に到達しているぐらい十分大きいなら、C 回違ってもちょう
ど閉路1周分違うので、到達する頂点は変わらない
– 始点aから k mod C 回動けばいい(厳密にはちょっと違いますが
後述)
? ひとまず k mod C を求めてみる
– 多倍長を使ってもOKですが、多倍長無しで簡単に求める方法
があります(桁DPなどでよく使うので、多倍長の付いた言語を
使っている人にも有用なテクです)
18. D問題 解法
? k の長さを L とおきます。
? k = (k の L-1 文字目までを整数として捉えたも
の)*10+(kの最後の数字の数) となる
– Ex. 334=33*10+4
– Ex. 123456=12345*10+6
? このことに注目すると、(kのL-1 文字目まで) mod C
が求まっていればよさそう。
? この1桁減らした数に帰結することを繰り返すと、
大きい数の桁から見ていき、今までの数に10を掛
け、今見ている桁の数を足す 操作を繰り返せば、
k mod C が求まる。
19. D問題 解法
– kを文字列として
保存するとこんな感じ→
? 始点 a からk mod C 回動けばいい
– ただし、k回移動したときに閉路に入っていることを仮定
していたので、 k mod C が T より小さいとき、T以上にな
る(移動後の場所が閉路に入る)まで移動回数に C を足
す必要がある
? つまり、k を移動後の場所が変わらない範囲で小さくしたかった。
k を k mod C にする操作は、kからCを引けるだけ引く操作なの
で、減らしすぎた分を戻す感覚
– k mod C < C <= N なので、シミュレーションは高々O(N)