たれながし

色々雑多に書きます

緑diff精進 その4 (1/26)

解いた問題

  • ABC045 C - Many Formulas
  • ABC102 C - Linear Approximation
  • AGC005 A - STring
  • APC001 B - Two Arrays
  • ABC114 C - 755
  • ARC140 B - Shorten ARC

ABC045 C - Many Formulas

atcoder.jp

感想 (解答中に考えたこと)

  1. evalで解けてしまいそうだが、本質じゃないので使わない。
  2. 各数字がどの桁で幾つ現れるかを考えれば良い。
  3. 基本的にどの数字も n桁目は 2^{|S|-n-3}\left( = C(n)\right)個現れる。ただし C(n)を現れる回数とする。
  4. また各数字が使える回数は数式のパターンの数分なので 2^{|S|-1}で、 Sにて k桁目であった数字が k+1桁目以降に現れるはずがない。よって k桁目の数字を S_{k}として、その寄与は \sum_{n=1}^{k-1}S_{k}\times 10^{n-1}\times C(n)\;\left(k\geq 2\right)。最後に S_{k}\times\left(C(k) - \sum_{n=1}^{k-1} C(n)\right)\times 10^{k-1}の分を補正すれば良い。

提出コード

まぁbit全探索で良い atcoder.jp

ABC102 C - Linear Approximation

atcoder.jp

感想 (解答中に考えたこと)

  1. 絶対値の和の最小化なので、どうせ中央値あたりを考えれば良さそう。
  2.  \sum |A_{i} - b - i| = \sum | B_{i} - b |のように変形すれば、 B_{i}の中央値を求めれば終わり。

提出コード

なんと、 B_{i}のソートを忘れていたらしく……(3WA) しかし数列の長さが偶数のケースを無視していたが、通ってしまった。 atcoder.jp

AGC005 A - STring

atcoder.jp

感想 (解答中に考えたこと)

  1. 左から消去っていうのが効いてきそう?とりあえずランレングス圧縮する。
  2. 左端の文字がTである場合は無視すれば良いので、Sから始まる文字列のみ考えれば良い。
  3.  nSが連なっているものを S(n)Tが連なっているものを T(n)とする。
    •  S(n)T(m)\;\left(n\leq m\right)であれば、消去操作は n
    •  S(n)T(m)\;\left(n\geq m\right)であれば、消去操作は m回で、次のSのまとまりの個数に n-mを加える。
  4.  |X| - 消去回数\times 2が答えになる。

提出コード

左から捜索して特定の文字列になったら削除はStackで管理、めちゃ典型だ……。 atcoder.jp

APC001 B - Two Arrays

atcoder.jp

感想 (解答中に考えたこと)

  1. APCなんてものがあるんですね……。 c_{i}=a_{i}-b_{i}で表される c_{i}からなす数列 Cを考える。ここで操作は以下のように言い換えられる。
    •  i, j \in \left[1, N\right]を選び、 c_{i}に2を加算。 c_{j}に-1を加算。
    • 上の操作によって全ての c_{i} 0にすることが目標。
  2. このことから x=-\sum_{i=1}^{N}c_{i}としたとき、 xが操作回数になる。これ以上操作をすると Cの和が1以上になるので一致することはなくなる。同様に x未満の操作回数でも一致しない。
  3.  Cの各要素から最短で 0にする方法を考える。また、 +2する回数と -1する回数を分けてカウントする。
  4.  c_{i}が正数であるならば、 -1をその数だけ繰り返せば良い。
  5.  c_{i}が負数であり、偶数であるなら +2をその数/2回繰り返す。奇数ならば(その数+1)/2回 +2を繰り返した後に -1を1回行う。
  6. 最後に +2 -1の回数および xから判定をする。
    •  -1の回数が +2よりも大きければNo
    •  +2の回数が -1よりも大きい場合、余剰分を +2を1回と +1を1回で繰り返せば Cの要素は全て0になる必要条件を満たし、操作回数が xと同じになればYes
    • その他回数が同じだった場合や xが負数の場合の処理を書けば良い

提出コード

ABC114 C - 755

atcoder.jp

感想 (解答中に考えたこと)

  1. 上位の桁を固定しながら和を取るのが簡単そうだが、同様のもので桁DPがある。練習がてら桁DPで解いてみる。
  2.  dp(i, j, k):=上から i桁目を見た時、数字の使われ方が状態 j (ビット)である場合の数。ただし kは上位 i桁目まで一致しているかどうかのbool値。
  3. 上位の桁を0埋めする場合が考えられ、また3057のように途中に0を入れてはいけないので、bitで探索するときも0のみ特別に扱う必要がある。
  4. あとは i桁目の数字と jの状態から丁寧に丁寧に丁寧に状態遷移を実装してあげれば良い。

提出コード

苦しすぎた…… atcoder.jp

ARC140 B - Shorten ARC

atcoder.jp

感想 (解答中に考えたこと)

  1. ARCであればどのタイミングで操作してもよく、AARCCであれば奇数回目で操作すると偶数回目でACまで変化できて嬉しい。つまりAARCCARCの個数がわかればよいのでは? -> WA
  2. 考えてみたがわからんので解説をチラ見。なるほど、A...ARC...Cを常に奇数回目で操作するようにすれば、両端のAあるいはCの個数の小さい数ぶん操作が可能になる。
  3. つまりランレングス圧縮する過程でA...ARC...Cの塊の情報を整理すれば見通しが良くなりそう。
  4. あとは奇数回目であればARC以外のものを優先して操作し、偶数回目であればARCを優先して操作することが必要になる。
  5. 実装方法に迷ったが、操作回数は高々 N回で抑えられるだろう(操作することにより、1文字あるいは2文字消去なので)。なのでpriority_queueを使って愚直に勘定するのが良い。

提出コード

atcoder.jp