3匹の猫

みみねこの競プロ精進メモ

AtCoder Beginner Contest 198参加記(~E問題)

コーナーケースに気を付けろ!!
     
f:id:mmnkblog:20210411231102p:plain

A - Div

A君が得るお菓子の個数をA個、B君が得るお菓子の個数をB個とすると、B=N-Aという等式が成り立つ。この式から、Aを固定するとB1通りに定まること、A, Bがともに正の整数でなければならないことを考えると、Aが取りうる範囲1\le A\le N-1の中にある整数の個数、つまりN-1が答えとなる。計算量は、O(1)

ちなみに制約がゆるいので、brainfuckでも簡単なif文の処理が書ければ解ける。

B - Palindrome with leading zeros

問題文中の操作は、「Nを文字列としてみたときの末尾から連続している0をすべて削除する」と言い換えられる。こうすることで、操作後の文字列N'が回文かどうかを一度判定するだけで答えが求まる。N=0のときの処理に注意。計算量はO(\log N)

C - Compass Walking

2歩歩くことで、ユークリッド距離が2R以内の点に移動することができる。また、x歩以下で到達できる範囲は、原点から距離がxR以内の範囲である。このことから、解xを二分探索して求めることができる。
ただし、1歩歩くことで到達できるのは原点からちょうどR離れている点だけであるので、二分探索して得られた解がx=1だった場合にのみ、原点からの距離で場合分けする。

二分探索について。ルートを使うと小数誤差にやられる危険性があるので、整数のまま計算する。具体的には、距離の大小さえわかればよく、距離は負の値を取らないので、距離の2乗をそのまま比較する。式は以下の通り。

X^2 + Y^2 \le x^2 R^2

また、解の最大値は2\times 10^5程度と見積もれるが、距離の2乗で比較する方針だと上式の右辺が最大で4\times10^{20}となりオーバーフローするので、二分探索するときの解の最大値は2\times 10^5\div rとした。こうすると右辺は単にx^2となる。計算量はO(\log (X+Y))

コンテスト中はこれで十分だが、より厳密に議論すれば二分探索を用いなくてもO(1)で答えを求めることができる(公式解説より)。考察をサボれるときはサボることも大事。

D - Send More Money

条件がごちゃごちゃ書いてあるが、普通に覆面算を解くだけの問題。各英小文字に一桁の整数を割り当てるので、文字の種類数が11以上ある場合は解なし。

文字の種類数が10以下だった場合、各文字に整数を割り当てる方法を全通り試す。文字の種類数をaとすると、{}_10 \mathrm{ P }_a通り試せばよいことになる。C++のnext_permutation関数に長さ10の順列を与えてループを回し、順列の先頭a個だけをみて実際に文字に割り当て、N_1 + N_2 = N_3が成立するか確かめる。計算量はO(N!)

E - Unique Color

与えられるグラフは木であるので、2頂点間を結ぶパスは必ず1つだけ存在する。もちろんそのパスが最短である。また、木の頂点1から頂点xまでのパス上に頂点yが含まれていた場合、そのパスに頂点1から頂点yまでのパスが完全に含まれている。

以上のことより、頂点1からDFSをして「よい頂点」でない頂点を探すこととする。具体的には、DFSをしながら通った頂点の色をメモしていき、頂点xの色がすでに登場しているなら答えから外す、ということをしていけばよい。

メモするための道具として集合(set、挿入・削除がともにO(\log N))を用いたがTLEしてしまった。setのかわりにunordered_setを使ってみたが変わらず。しかもこの方法はメモリも大量に使うため非常に重い。
もう少し考えると、DFSで戻ってくるとき「どのタイミングで色cが使われなくなったか」は「どのタイミングで初めて色cが使われたか」の解と等しいため、setを使わず、bool配列で管理することができる。
計算量は、O(N)

F - Cube

むずすぎ

感想

青パフォだったのでうれしいけど、Eでの2ペナがもったいないと思った