A. Anti-Adjacency
選ぶ数の最大値をなるべく小さくしたいことから,1から1つ飛ばしで数を選んでいくのが最適.このときk個目(k=1,...)の数はk番目の正奇数,すなわち2k−1であるから,これとnとの大小を比較する. 解答例
B. Path
問題文の処理をそのまま実装するDFSを書いた.道に番号を振ってそれぞれの道を通ったかを配列で記録しておけば,3回の移動で「すべての道を」「1回ずつ」通ったかは迷いなく判断可能. 解答例
editorialの解法は漏れを作りそうなため,個人的にはこちらの解法のほうが好ましく思う.
C. When I hit my pocket...
こういう操作の特性を考える系の問題はあまり得意ではない.実験をした. 解答例
本文中にある操作を上からP,Q,Rとする.最終的に円を持っていても利益がないので操作Q,Rの数は同数.すると例えば操作列はPPPQRPPQQRRP...
のようになるが,P...PQR...QR
と整列して構わない.このときP
の数をp,QR
の数をqとすると,p+2q=k.
このときのスコアはp+1+(b−a)q =(k−2q)+1+(b−a)q =(b−a−2)q+k+1.
qの係数が負または0,すなわちb−a≤2の場合はqが少ないほうがよく,q=0としてスコアはk+1.そうでない場合はqは多いほうが良い.ただし操作Qを行う条件としてp≥a−1,変形してq≤2k−a+1が必要であり,q=⌊2k−a+1⌋としてスコアを算出すればよい.ここでq≥0にも注意:qが負のときはq=0とする.
最初はpについて整理しようとして散々な目に遭った.q=2k−pを用いるとp+1+(b−a)q =p+1+(b−a)(k−p) =p(1−(b−a))+1+(b−a)k.b−a>1のときはpの係数が負なので操作Q,Rを増やすべきだが,操作Qを行う条件としてp≥a−1.素直にp=a−1としたいが,qは整数なのでk−(a−1)の偶奇で場合分け:偶数のときはそのままq=2k−(a−1),p=a−1.奇数のときはq=⌊2k−(a−1)⌋ (=2k−a)としてしまうと1操作余るため,それを操作Pに回してp=a,q=2k−aとする.というように,pについて整理するほうが面倒.
ところでeditorialでは最初からb−a≤2かを見ている.これは操作QR(スコア+(B−A))と操作PP(スコア+2)の比較と見れば納得できる:b−a≤2であれば後者を選んだほうがよく,b−a≥2であれば前者を選んだほうが得をする.
D. Ears
散歩が1回だけという条件を読み落としていたが,そうでなくても解けなかったと思う.
解説(editorialなど)
まず散歩により耳がどうなるかを考えると,これは[0]*-[偶数≥2]*-[奇数]*-[偶数≥2]*-[0]*という5つの区間が並んだ形になる.逆にこの条件下であれば任意数の石を入れることができる.
この結果の導出についてはこちらの記事が大変参考になった:始端→終端という一番単純な形から考えてみる.この2点を固定すると,散歩のバリエーションとしてあり得るのは途中箇所に往復を加えたものだけであるから増分は必ず偶数となり,ここから導かれる.
以下では当該記事も含めた2記事を参考文献としている(後掲する).
本問で行う操作は次の2つ:
- 散歩によって位置iの石の個数をb[i]とする
- 各b[i]に好きな回数だけ±1をし,b[i]=a[i]とする
各位置iが散歩のときどの区間だったのかを考える.先に述べた区間を順にZl,El,O,Er,Zrとする.
前の数字が区間Aであるとすると区間の順序から位置i+1はA以降の種類のどれかになるはずであり,逆にどれになっても構わない.
位置iが当て嵌まる区間の種類を仮定すると,a[i]の値から必要な操作の回数もわかる(先に述べたようにb[i]が好きなように作れるため):
- a[i]がZl: b[i]=0からa[i]回操作を行ってa[i]にしたとするのが最小
- a[i]がEl: b[i]は2以上の偶数であることから,
- a[i]=0のとき操作は2回(b[i]=2として−2する)
- 2以上の偶数のとき0回(そのまま)
- 奇数のとき1回(b[i]=a[i]+1とすると,操作で−1することでa[i]が作れる)
- a[i]がO: b[i]は奇数であるから,
- a[i]が奇数であれば操作は0回
- 偶数であれば1回(b[i]=a[i]+1とする)
- a[i]がEr: Elと同様
- a[i]がZr: Zlと同様
肝心の区間を決めたい.以前に「区間の境界を1つ決めると残りの境界も決まる」というタイプの問題を見たことがあるが今回はたぶんそうはならない.DPができる:dp[i][K]:=「a[i]が区間Kであるときの操作回数の最小値」とすると,先に説明したように区間の遷移を書ける.すなわち区間Kに対して先の操作回数をfK(a[i]),Kまたはそれ以前の区間の種類をP(K)とおくと:
dp[i+1][K]←J∈P(K)min{dp[i][J]+fJ(a[i])}
となる.配るDPとして解釈したほうが先の記述に合っているが,配るDPを式で書くときの慣例がよくわからず.
計算量はKが5通りなのでO(L).考察さえ済めばかなり綺麗に書ける. 解答例
参考
- https://betrue12.hateblo.jp/entry/2019/02/10/014031
- http://koba-e964.hatenablog.com/entry/2019/02/10/003030