AtCoder Beginner Contest #121

published: ,
last modified: .

lang: ja

category: competitive_programming

tags: atcoder ocaml

A. Cells

残った白い部分を左上に詰めると考えやすい気がする(ABC106Aの解説のように). 解答例

B. Can you solve this?

Yes. 数式をそのまま実装すればよい. 解答例

C. Energy Drink Collector

安いものから買っていくのがよいから,(値段,個数)のペアを値段で昇順ソートし,この順番に残り購入数が00になるまで買う.C++だと結構大変そうだがOCamlだと楽できる. 解答例

D. XOR World

bitごとに決めていく解法はすぐに浮かんだものの実装が複雑になってしまったため考察をした.この種の問題に適用できる定石をすっかり忘れていたので反省. 解答例

偶数とその次の数とのxorは必ず11である.これは最下位ビットが00から11になるだけの違いであるため.この性質を利用するために偶数と奇数のペアを基調に考えていく.

これによってaaに最も近い偶数からbbに最も近い奇数までのxor結果はO(1)O(1)で求まる:a,ba,bの偶奇で場合分けすると,左端llaaが偶数のときはaaを選べばよく,奇数のときはa+1a+1.右端rrbbが奇数のときbb,でなければb1b-1l>rl \gt rとなるような場合,すなわちb=a,a+1b=a,a+1の場合は個別に処理しておく).この中のxor結果は,偶数と隣り合う奇数のペアが(rl+1)/2(r-l+1)/2個存在することから,これが奇数であれば11,偶数であれば0 (11=0, 01=1)0\ (\because 1 \oplus 1 = 0,\ 0 \oplus 1 = 1)

あとは余りを処理すればよい.まずl=a+1l=a+1のときはaaと先の結果とのxorが必要.右側についても同様に,rrbbを比較してr=b1r=b-1であればrrとのxorも計算する.これにより所望の値が求まる.

別解1(editorial)

区間[a,b][a,b]に関する問題は[0,x][0,x]の解が求まれば[0,b][0,b][0,a1][0,a-1]の結果から求められる場合がある,という定石を用いるのが簡単だった.いまそれぞれの範囲のxorは先の方針の一部であるから簡単に求まる.ここでxorの逆演算がxorであったことを思い出すと,([0,b])([0,a1])(\oplus [0,b]) \oplus (\oplus [0,a-1])を計算すればよい(記号は適当). 解答例

別解2(editorial)

先に述べたビットごとに決めていく解法のリベンジ.やはりaabbを同時に考えるのは厳しそう.そこでこの解法でも[0,x][0,x]を求める方法から考えることとする.

まずxorは桁ごとに考えることができるため,そのようにする.いま00からxxまでの整数を2進数表記で並べると,各ビットii(下から順に0,1,...0,1,...とする)では00,11のそれぞれ2i2^i個の並びが交互に現れる.いま一つの0...01...10...01...1を1単位と考えると,1単位分のxorの値は11の個数からi=0i = 0のとき11,それ以外のとき00である.[0,x][0,x]において,iiビット目までにある単位数ccは切り捨てで(x+1)/(2×2i)(x+1) / (2 \times 2^{i})個であるから,繰り返し部のxor和はi=0i=0のときcmod2c \bmod 2,それ以外のとき00である.

加えてループの余り部分も考える必要がある.この長さll(x+1)2i+1c(x+1)-2^{i+1} cとなる.これが2i2^iを超えている場合はその数だけ11が含まれるため,(l2i)mod2(l-2^i) \bmod 2を計算すればよい.これと先のxorの値とのxorをとれば,それがその桁の値となる. 解答例