AtCoder Beginner Contest 138

2日連続でACのコンテストじ

 

 

 

A - Red or Not

3200未満がredで3200以上がsと出力する

 

逆じゃん!というネタですね。

redじゃなくてresとtypoして危うくペナ踏むところでした。あぶねえ

 

 

 

 

 

 

B - Resistors in Parallel

問題:逆数を足したものの逆数をとる

 

 

やるだけですが、小数点以下を表示させる方法知らないと厳しいです。

というかググれば出てきます。

 

 

 

 

 

C - Alchemist

問題:価値vのものがn個あります。n-1回操作をします

操作:価値xと価値yのものを除いて価値(x+y)/2のものを加える

最後のものの価値を最大化せよ

 

 

 

考察:

3つで考えます。それぞれの価値はx、y、zです

前からマージするとき最後に残るものの価値wは

((x+y)/2+z)/2

=x/4+y/4+z/2になります

最後のほうにマージしたほうが寄与が高いので、昇順にマージすれば最適です。

 

 

 

 

 

D - Ki

問題:n頂点の根付き木が与えられます。クエリQ個を処理した後の各頂点の値を求めよ

クエリ:頂点pの部分木にxを加える。

 

 

考察

愚直にやったら無理そうです。

なので、先にクエリを読みます。

 

ある頂点vを部分木の一部とする根頂点は、vから根1までのパスに含まれます

はじめ各頂点で求めようとしたんですけど、dfsしながら子に答えを足していけばよいことに気づきました。

 

 

 

ついったで話題になっていたんですが、根付き木の辺は無向か有向かということでした。

調べた感じだと無向辺になりそうです。

 

ただ問題文が「根付き木が与えられる」となっていたので、各頂点の親を与えるような感じですよね。入力形式に違和感を感じました。

 

まあ自分の知識不足をテストケースの弱さに助けられた部分もあるのでこれからは気を付けます。

特に記述がないときは無向辺として処理しましょう。

 

 

 

 

 

 

E - Strings of Impurity

問題:文字列s、tが与えられる。sを無限につなげたssの前からk文字が、(連続しなくてもよい)tの部分文字列(subsequence?)になるような最小のkを求めよ

 

 

 

考察:

愚直に考えると、tの各文字についてsのindexを進めていき、一致したらtを先に進めるとすればよいです。

 

このままでは最大で|s||t|かかるので間に合いません。

アルファベットごとに整理しておくと、二分探索で高速化できます。

 

開始位置が1になっていて1ペナくらいました。もったいない。

 

 

 

 

 

F - Coincidence

問題:L<=x<=y<=Rであるx、yでy%x==x^yとなるx、yの組の数を求めよ

 

 

考察:

まずy%x=zとします。

x>zより、yとxで桁が違うと成り立ちません。

なぜならx^y>xになってしまうからです。

 

 

各桁数で調べればよいです。

xi,yi:x、yのiビット目とします

x<=yから、0,0  0,1  1,1の3通りになります。

 

k+1桁の整数を調べるとき、2^k~2^(k+1)-1が対象です。

[L,R]に含まれている場合3^k通りです。

 

中途半端なときだけ考えればよくて、これは桁DPでできます。

バグります。終わりです。

 

 

※やーーっと通せたので追記

3つの関数を定義します。

calc_x(k):xがL以上を満たすようなk桁の場合の数。y<=Rが常に成り立つ

calc_y(k):yがR以下を満たすようなk桁の場合の数。x>=Lが常に成り立つ

calc_xy(k):L<=x<=y<=Rを満たすようなk桁の場合の数。

 

まずx、yのみで考えます。

k桁なので1<<kがあります。

k-1~0桁目での挙動を考えることになります

Li=1:xi=0にすると必ず小さくなるので1にするしかないです

Li=0:xi=1にすると必ず上回るので残りのbit分の3^(i-1)通りがあります。

   xi=0にする場合のみを次から考えます。

Ri=1:yi=0にすると必ず下回るので残りのbit分の3^(i-1)通りがあります

   yi=1にするときのみ次にいきます

Ri=0:yi=1にすると必ず大きくなるので0にするしかないです。

 

以上からcalc_x,calc_yではx、yを1つに決めながら下の桁へ進めます。

次に進むとき上の桁が2通りあることに注意しましょう。

 

 

次にcalc_xyを考えます。

上を組み合わせて、矛盾が生じるところはreturn

どちらかだけ自由になればcalc_?を呼び出しましょう

どちらも自由になることはありません。

 

 

最後にx=Lやy=Rに定まっているので、その分を足したら答えになります。

 

 

 

bitごとでよいことに気づいたら素早く実装できました。

桁DPと、bitの扱いに慣れていなかったのが敗因ですね。

0か1しかないというのはすごく扱いやすいことだなと実感しました。

 

 

 

感想

久しぶりにABCであったまりました!

というかF解いた人が少なかったからですけどね。

Eまではまあ早くもなく、遅くもなくというか、1ペナが大きかったくらいです。

 

1.5か月のコンテストでレート伸びたのが1回で+16だったので、昨日今日で+113してるのは非常にうれしいです。

 

まあHighestじゃないんですけど

 

 

とにかく、慢心せず黄色目指して頑張ります。またな