ABC 097 C - K-th Substring
ABC 098 D - Xor Sum 2
最近しゃくとり方を実装していなかったので解き直しました.
解法
問題を見るに, いかにもなしゃくとり法です.
この問題を解くうえで, xor演算の重要な性質を用います.
xor演算において以下の性質が成り立ちます.
1の性質は, この演算においては自身が逆元となることを示しています. (自明に0が単位元となっています.)
2の性質は, 可換な演算であることを示しています.
3の性質は, 結合法則が成り立つことを示しています.
これを利用すると, しゃくとり法を実装することができます.
具体的には, 以下のアルゴリズムを適用することができます.
入力の配列を, サイズをとします.
- 初期化 :
- ならばを出力して終了する.
- ならば4へ, そうでなければ5へ
- , , , 2へ
- , , 2へ
しゃくとりの右端を右に進めるときに答えを加算するようにしています.
計算量はで済みます.
感想
しゃくとり法は本番でバグらせやすいので演習を積んでいきたいです.
ABC 109 反省
久々にコンテスト中に全完できました. しかし, B問題でWAを連発してしまったため, 大きくペナルティを食らってしまったのは反省事項です.
A問題
問題
解法
を1~3まで試します.
感想
素直に実装しましたが, が奇数だったら"Yes", そうでなければ"No"です.
B問題
解法
次の文字の先頭と今みている文字の尻が一致しているかをみるついでに, map
感想
yukicoder解いてるときにWAが出るとすぐテストケースをのぞいてしまう癖があるので, こういう不測のWAに弱いとこがありました. 反省します.
C問題
問題
解法
すべてのに対しての差分を取り, これらすべての最大公約数が答えとなります.
各の間の距離がの倍数であり, さらにから距離でステップしてどれかのに到達することができれば, で数列間を移動することができます. その中での最大のは, 各に対してすべての最大公約数となります.
感想
解法はなんとなく思いついたのですが, 説明がなんとなく難しいです.
D問題
解法
発想が必要になる問題です.
まず, の制約から, の解法が求められます.
これがちょっとしたヒントで, 何度もバックトラックして計算するようなことはなさそうであることがわかります.
操作について考察します.
できるだけ偶数マスを増やしたいときは, 奇数マスのコインをどこかに動かせばよいのですが, ここで動かす方向を下方向に固定してみます.
まず1行目を左から右に見て奇数マスのコインを下に動かし,
次に2行目を...として,最後から2番目の行まで繰り返します.
すると, 最後の1行以外のマスをすべて偶数マスにすることができます.
最後の1行については, 奇数マスのコインを順次右側に動かしていくと, 一番右下のマス以外すべて偶数のマスにすることができます.
コインの総数が奇数だった場合, どうしても奇数のマスは1つできます.
コインの総数が偶数だった場合, すべて偶数のマスにできます. このとき, 右下のマスが奇数で他のマスが偶数ということはありえないので, これが最適解であることがわかります.
あとはpairとvectorなどで移動元と移動先を管理し, 丁寧に実装しましょう.
0-indexedで出力してしまい1-WA.
感想
0-indexedで出力してしまったのはちょっとした悔いですが, 解けてよかったです.
総括
最近難しいABCが続いてましたが, 今回は易しかったように思います. ただ, こういうときにWA量産して順位落としちゃうのはよくないですね.
yukicoder No.420 mod2漸化式
最近はyukicoderの低難易度埋めてます.
その中でもおもしろいと思ったものを書き留めます.
解法
まず漸化式
がそもそも何を表しているか考えます.
ためしにいろいろ入れてみると,
...
となります. のべきがとなっているところや, 数字の増え方をみると, この漸化式は(というより関数としてみると)あるを進数表現したときの立つ1の数, または各桁の和であると推測することができます. その観点を持って漸化式を見ると, たしかにそれらしいことがわかります.
問題に戻ります. 問題では, あるが与えられ,
- となるようなの数
- それを満たすの和
の2つを求める必要があります. 上の考察より, 前者は31ビット分の中に1を個立てる場合の数を求めればよいです. これは, で求まります.
後者は少し考察が必要です. 上で求めたの中で, 番目のビットにが立つ場合の数はいくらか?を考えます. この数は, ビット目に1を立てておいて他の場所に個1を立てたときの場合の数に対応するので, に対応します.
よって, ビット目に1が立つものは 個あり, このを1から30について計算するので,
となります. コンビネーションの部分は外に出せ,
となり, さらに簡略化すると,
となり, これが和の方の答えです.
しかし, が0のときだけ場合分けが必要なので注意です.
感想
漸化式の意味を理解すると大きく計算量を減らすことができる面白い問題だと思いました.
ARC 102 C - Triangular Relationship
解法
コンテスト中は, ひたすらを固定しての数を数える方法を探していた.
まず, 問題文を式に表してみると,
を固定してみたときとりあえずは
表すことができる. また,
より
が成り立ちます.
また, 条件から各について
より
について
が成り立ち, についても対称性から同じものが成り立ちます. これを変形すると, について
となり, についても
が成り立つ必要があります.
いま, を固定しているため, 不等式からとが取りうる値の数を求め, 掛けあわせれば場合の数を求めることができます(同じ式の形なので, 片方を求めて二乗すればよい).
しかし, 式
はを固定することにより得ているので正しいが,
は, との値によっては成り立たない場合があります.
がの倍数でないときはこの式を満たすことはできません. 逆に, がの倍数のときは, 両辺をで割り, を導出することができるため, がで割り切れることは, この式を満たす必要十分条件となっています.
よってその場合のみ数を数えないことにします.
これをについて行い, すべての場合の数を足しこむと答えが得られます.
SoundHound Programming Contest 2018 Masters Tournament 本線 B - Neutralize
解法
貪欲ができないか考えます.
ある薬品を0にしたいときはK個を巻き込む必要があります. また, 個以上の区間を0にしたいときはこれを繰り返すことで実現することができます.
しかし, サンプルケースを見てみるとこれは厳しそうであることがわかります.
最適解が貪欲に求まりそうにないので, 最適解を仮定してDPをすることになります.
DPをするにあたって必要な保持状態は、まず
- 見ている薬の番号(1からN)
が必要です. 他に必要なものは,
- 見ているインデックスを右端としてK個選び, 0にしたかどうか(True or False)
です.
この2つを規定すると,
基底
感想
なかなかに大きい制約なので DPはなかなか発想できません.
No.672 最長AB列
解法
まず愚直解を考えます.
左端を決めて左から文字列を見ていき, A, B,の数を数えながら右に行き, AとBの数が同一になったら最大値を更新します.
この解法はでTLEです. この解法を詰めていきましょう.
まず,ABの数が同一ということはAを1, Bを-1とすると和が0となるということです. これの累積和をとっておき, 区間が与えられたらでその区間のABの数が同一かどうかを答えられるようにしておきます.
ある2つの区間の端を選ぶと, 対応する累積和があります. その累積和の差が0であると, その 区間のABの数は同一ということになります.
上の考察から, ある区間の左側を決めたときに, それに対応する累積和と同一のものが右側に存在するか?を考えればいいことがわかります.
このときに選ぶ右端は, できる限り右側のものを選ぶと, 区間が大きくなります.
よって, 累積和をとるときにある累積和の数値をとったもので最大の添字を持つものを一緒に保存しておけばいいことがわかります.
mapで上を実装すると, 計算量はで抑えられます.
感想
はじめは累積和をとって二分探索するものかと思いましたが, 単調性の反例が見つかり断念.
こういった問題は愚直解から詰めていかないと考察が難しいですね...
類題としてAGCのZero Sum Rangeなんかが挙げられます.
区間の左側を決めた時に最適な右側を高速で導出するのは結構典型ですね.