AOJ 0289 - Infinite Express
むひゃー.
解法
非負整数nの最右ビットをrms(n)で表す.ただし,rms(0) = 2^30とする.
例. rms(5) = 1 (5 = 0b101),rms(6) = 2 (6 = 0b110)
(n>0ならば,このrms(n)はn & -nと書ける.BITでおなじみ.)
位置sにいるとき,i級快速(iは1<=2^i<=rms(|s|)を満たす整数)に乗ることができる.
このとき,位置dを越さない最大のiを選ぶ.これを位置dにたどり着くまで行なったときの回数が最小回数である.
コード
#include <iostream> int main(){ int N, s, d, t, s_, mx, i; std::cin >> N; while(N--){ std::cin >> s >> d; t = 0; while(s != d){ s_ = std::abs(s); mx = s_ & -s_; if(!s){mx = 1 << 30;} for(i=mx;;i/=2){ if(s + i <= d){s += i; break;} } t++; } printf("%d\n", t); } }
ショートコード
短くしてみた.Nいらんやろと思ったが,そうするとREが出たので入れた.
PCK公式の解説にはより短そうなの(しかも,ショートコーディングは意図していない)があったので,Ω\ζ°)チーン.
main(N, s, d, t, i){ for(scanf("%d",&N);N--;){ for(t=!scanf("%d%d",&s,&d);s-d;t++){ for(i=(i=abs(s))?i&-i:1<<30;;i/=2){ if(s + i <= d){s += i; break;} } } printf("%d\n", t); } }