🍣

AtCoder Beginner Contest ABC412 解法メモ

に公開

文中で使用しているのは、PythonライクでAtCoderに最適な言語の1つNimです

ABC412

ABC412A - Task Failed Successfully

解法

(0..<N).toSeq.countIt(Ai<Bi)
ACコード

ABC412B - Precondition

解法

(1..<S.len).toSeq.allIt(S[it].isLowerAscii or (S[it].isUpperAscii and S[it-1] in T))
評価は2文字目から行えばよい
ACコード

ABC412C - Giant Domino

解法

着目しているドミノで最後のドミノが倒せるかを判定、
駄目なら、着目しているドミノの大きさの倍以下で最大の大きさのドミノを貪欲に選択し続けていけばよい
間にあるN-2個のドミノの大きさをソートした配列をsとする
着目するドミノの大きさをhとし、初期値として左端のドミノの大きさS[0]とする
答えである使うドミノの個数をaとし、初期値を左端分の1とする
以下を繰り返していけばよい
・h*2>=S[^1]であれば、右端のドミノ分の1を足して答えであるa+1を出力して終了
・次のドミノs[i](2番目からなので)がh\times 2より大きくて倒せないか、(i=N-2となって)sを最後までみてしまった(それなのに右端のドミノが倒れなかった)ときは、-1を出力して終了
i二分探索でs[i..^1].upperBound(h*2)+iに更新する
ACコード

メモ

while内の条件不足で無限ループを作ってTLEしているのに、計算量過多と誤認して無駄な考察を繰り返した
2^{30}=1073741824>10^9ゆえ、ちょうど倍々の大きさのドミノがあれば30個、最悪でもその間を繋ぐドミノを置けばよいから必要なドミノは高々60個程度となる。それゆえ、ソートもせずに、都度都度全てのドミノの大きさを確認して回ったところで、充分に間に合う
ACコード

ABC412D - Make 2-Regular Graph

解法

頂点数が高々8なので、全ての次数が2の、輪を形作る場合、連結成分(輪)が1つか2つに限られる
その完成形に対して、すべての頂点の組み合わせを列挙し、与えられた辺との差分をとればよい
具体的には、1〜Nのすべての順列に対し、
①最初と最後を繋ぐ(連結成分1つ)
N=6なら、3番目と1番目、6番目と4番目を繋ぐ(頂点3つずつの連結成分2つ)
N=7なら、3番目と1番目、7番目と4番目を繋ぐ(頂点3つと4つの連結成分2つ)
または、4番目と1番目、7番目と5番目を繋ぐ(頂点4つと3つの連結成分2つ)
N=8なら、3番目と1番目、8番目と4番目を繋ぐ(頂点3つと5つの連結成分2つ)
または、4番目と1番目、8番目と5番目を繋ぐ(頂点4つずつの連結成分2つ)
または、5番目と1番目、8番目と6番目を繋ぐ(頂点5つと3つの連結成分2つ)
の各々の辺の集合sと、入力で与えられる辺の集合eに対する、
((e-s)+(s-e)).lenの最小値が答え
ACコード

メモ

グラフでの解決にこだわり過ぎた

ABC412E - LCM Sequence

解法

出力例1でわかる通り、Aiは、前項と同じか、大きくなる
同じ、ということは、新たに加わる数がそれまでの素因数分解の組み合わせの範囲内で表現できるということで、逆に増えるタイミングというのは、素因数分解の指数の上限が上がるか、新たな素数が加わるタイミングだといえる
そのタイミングとは、素数冪(1つの素数の冪乗だけで表される数)が加わるとき、と言えるので(そうでなければそれより手前で出現しているはずだから)、区間内の素数冪の数を求める問題、と言い換えることができる
これはいわゆる区間篩で、通常のエラトステネスの篩同様、
\sqrt{R}までの素数を列挙し、
1からRまでの配列は大き過ぎて用意できないので)区間の幅であるR-L(初項は別に素数冪でなくとも必ず答えの中に入るのでL+1からRの間)の要素を持つ配列を用意、
列挙した素数pそれぞれについて、p^2以降のpの倍数(つまり合成数)を篩にかけて落としていく(p^2未満は、pより小さい素数の篩にかかる)
もちろん、p^2L+1より小さければ、L+1以降のpの倍数をみていけばよい
篩にかける際、並行してp^nとなる場合をカウントし、篩に残った素数に加えればよい
ACコード

メモ

区間内の素数冪の数を求める問題、との言い換えができない
区間篩という実装の工夫を知らない


反復学習にはmochiがおすすめ
全問入ったdeckはこちら

Discussion