Dive into Coding Life

AtCoder:4 ABC081B – Shift only

25/12/2020

https://atcoder.jp/contests/abs/tasks/abc081_b
問題文は上記リンクを参照。

このあたりからコードが人によって結構違ってきますね。
自分がこう書くであろうという前提が人によって結構違うことがわかるので興味深いですね。

println(Array(n) { Integer.numberOfTrailingZeros(scanner.nextInt()) }.min())

https://atcoder.jp/contests/abs/submissions/18805628

numberOfTrailingZeros()の使い方を知らないとこのコードは書かないと思いますが、同等のコードをこんなに短く欠けるんですね。

numberOfTrailingZeros()は引数の値を二進数としてとらえ、右から0の数を数えます。
引数が2の場合、二進数で10なので、Integer.numberOfTrailingZeros(2) = 1
引数が4の場合、二進数で100なので、Integer.numberOfTrailingZeros(4) = 2
引数が6の場合、二進数で110なので、Integer.numberOfTrailingZeros(6) = 1
引数が8の場合、二進数で1000なので、Integer.numberOfTrailingZeros(8) = 3
ここで導き出されている解は、引数の値が2で何度除算できるかを表していますね。
これは二進数のシフト演算で右に1ビットシフトすることと2で除算することは同じであること、そして二進数で一番右のビットが0の場合は0、または偶数であるという性質を利用しています。

numberOfTrailingZeros(0)は32を返すという仕様がありますが、今回の問題条件として1以上の値が渡されるので、0を考慮する必要はありません。

読み込んだ各値に対しこの処理を行い、その最小値を取得すれば求める値がわかる、というわけですね。