情報妖精の競プロ日記

AtCoderの問題に対する方針を主に書きます

AtCoder Beginner Contest 150

AtCoder Beginner Contest 150(ABC150)に参加しました!

解けた問題だけ解説をしていきますー

要項

AtCoder Beginner Contest 150
rated ~1999
2020/1/10(金) 21:00 ~ 22:40 (100分)
100-200-300-400-500-600 (6問)
ペナルティ: 5分

方針

全完

A - 500 Yen Coins

問題文

高橋君は500円玉をK枚持っています。これらの総額がX円以上である場合はYesを、そうでない場合はNoを出力してください。

制約

  • 1 \leq K \leq 100
  • 1 \leq X \leq 10^5


解法持っているお金は500K円なので、これがX以上か判定すれば良いです。

感想最初の問題なので、やるだけです。

B - Fusing Slimes

問題文

英大文字のみからなる長さNの文字列Sがあります。
Sの連続する部分列としてABCがいくつ含まれるかを求めてください。

制約

  • 1 \leq N \leq 50
  • Sは英大文字からなる。


解法殆どの標準ライブラリには、部分文字列を取り出す関数や文字列の比較を行う関数が備わっています。
例えばJavaの場合、String.substring(i - 2, i + 1);でi-2文字目からi文字目までの文字列を切り出すことができ、String.equals("ABC")でその文字列がABCと一致するか比較することができます。
従って、後はこの開始点iを2からNまで動かせば良く、これはfor文などで実現できます。

感想標準ライブラリを知っておくと便利なことが多いので、調べて損は無いと思います。
そもそもそのライブラリが標準に入っている理由は、需要が高かったからなのですから。

C - Count Order

問題文

大きさNの順列 ((1,~2,~\cdots,~N)を並び替えてできる数列)P,~Qがあります。
大きさNの順列はN!通り考えられます。このうち、Pが辞書順でa番目に小さく、Qが辞書順でb番目に小さいとして、|a - b|を求めてください。

注記

2つの数列X,~Yについて、ある整数kが存在してX_i = Y_i~(1 \leq i < k)かつX_k < Y_kが成り立つとき、XYより辞書順で小さいと定義されます。

制約

  • 2 \leq N \leq 8
  • P,~Qは大きさNの順列である。
  • 入力は全て整数である。


解法nextPermutationというアルゴリズムが存在します。
詳しくは調べていただけると分かるのですが、ある列の辞書順で次の列を求め、また辞書順で次の列が存在するか判定してくれるアルゴリズムです。
これを用いると、それぞれの順列が辞書順で最も大きい順列から何個離れているかを求めることができるので、後は差を取ると判定できます。

感想これの上位版の問題として、辞書順で何番目?が存在します。
こちらの問題は順当な考察から解くので、もし良ければこちらもやってみてください。

D - Semi Common Multiple

問題文

長さNの偶数からなる正の整数列A= {a_1,a_2,...,a_N}と、整数Mが与えられます。
任意のk(1 \leq k \leq N)に対して以下の条件を満たす正の整数XAの「半公倍数」と定義します。

  • X= a_k \times (p+0.5)を満たす負でない整数pが存在する。

1以上M以下の整数のうちのAの半公倍数の個数を求めてください。

制約

  • 1 \leq N \leq 10^5
  • 1 \leq M \leq 10^9
  • 2 \leq a_i \leq 10^9
  • a_iは偶数である。
  • 入力は全て整数である。


解法制約よりa_iは偶数なので、b_i=2a_iと定義します。
この時、X= a_k \times (p+0.5) = 2b_k \times (p + 0.5) = b_k \times (2p + 1)と変形され、問題は全て整数で表すことができます。
この時、\frac{X}{b_k} = 2p + 1と表せることから、Xは任意のb_kの倍数である、すなわちb_1, \cdots, b_Nの公倍数であることが分かります。
b_1, \cdots, b_Nの最小公倍数をLCMとすると、Xは整数cを用いてX=c \times LCMと表すことができます。
また、X = c \times LCM = b_k \times (2p + 1)より、c \times \frac{LCM}{b_k}は奇数である必要があります。
ここで\frac{LCM}{b_k}が偶数であるならば任意の正の整数を掛けても偶数なので、条件を満たすXは存在しません。
逆に任意のkについて\frac{LCM}{b_k}が奇数であるならばcが奇数の時に条件を満たします。
従って、X=LCM, 3 \times LCM, ..., (2d - 1) \times LCM \leq M < (2d + 1) \times LCMを満たすような整数dが答えとなり、これは式変形すれば求まります。
LCMを求める際、最小公倍数がオーバーフローする可能性には気を付けましょう。
例えば実装の工夫として、最小公倍数を求める場合には2項の最小公倍数の公式lcm(x, y)=\frac{xy}{gcd(x, y)}を用いてLCM=lcm(b_1, lcm(b_2, \cdots, lcm(b_{N-1}, b_N)))と解くと思いますが、この際の各lcm(x,y)は高々2乗に収まる、すなわち10^{18}程度に収まることを利用して、もしlcm(x, y) > Mならばlcm(x, y)=M+1とするとオーバーフローを防げます。

感想重いし罠があるし400点問題としては難しい分類の問題です。
ついでに言うとテストケースも誤っているし、正直言って辛いね……。

E - Change a Little Bit

問題文

0, 1からなる長さNの異なる2つの数列S, Tに対し、関数f(S, T)を以下のように定めます。

  • Sに対し以下の操作を繰り返してTと等しくすることを考える。このとき行う操作のコストの和として考えられる最小の値がf(S, T)である。
  • S_iを (0から1、もしくは1から0に) 変更する。この操作のコストは、変更の直前にS_j \neq T_j (1 \leq j \leq N)であったような整数jの個数をDとして、D \times C_iである。

0, 1からなる長さNの異なる2つの数列の組(S, T)2^N \times (2^N - 1)通り考えられます。これらすべてに対するf(S, T)の和を10^9+7で割った余りを計算してください。

制約

  • 1 \leq N \leq 2 \times 10^5
  • 1 \leq C_i \leq 10^9
  • 入力は全て整数である


解法まず、同じ数列の組が存在したとしても答えに影響はしない(そのような数列のコストは0である)ので、同じ数列の組を許容します。
また、数列S'=0,0,\cdots,0とし、数列T'i番目の項をS_iT_iの値が異なるなら1、そうでないなら0と定めた新しい数列を考えると、元の数列から新しい数列へは一対一に対応するので、元の問題の代わりに数列S', T'について解いても一般性を失いません。
この時、数列S'は常に0であることから、ある数列(S', T')に対応する数列(S, T)は全部で2^N個あることが分かります。
従って、各数列T'について解き、その答えを最終的に2^N倍すると元の問題の答えになることが分かります。
さて、ある数列T'についてある数列pが存在してT'_{p_1}, \cdots, T'_{p_n}1であり、このpの順に操作するとします。
この時のコストは\sum_{i=1}^{n}{i \times C_{p_i}}であることから、pの順番はC_iの大きい順にすることが最適であることが分かります。
よって、まずCを降順ソートしておくものとします。
次に、T'について各C_iが何回コストとして数えられるかを考えます。
まずT'_i1であるような組合せは明らかに2^{N-1}通りあります。
また、T'_i1であり、かつT'_j (j < i)1であるような組合せ(先にjを取るためにiが複数回数えられる)は各jについて2^{N-2}通りあります。
従って、各iについてC_i(i+1) \times 2^{N-2}通りあることが分かるので、最終的なコストは2^N \times \sum_{i=1}^{N} C_i \times (i + 1) \times 2^{N-2} = 4^{N-1} \sum_{i=1}^{N} (i + 1) C_iです。

感想期待値の線形性など、何が独立に数え上げられるかを知っていると割と自明に見える問題だと思います。
この手の言い換えは高校数学でも頻出なので、もし良ければ数Aなどを勉強してみると良いのかもしれません。

F - Xor Shift

問題文

非負整数からなる長さNの数列a=\{a_0,\ldots,a_{N-1}\}b=\{b_0,\ldots,b_{N-1}\}が与えられます。
すぬけ君は0 \leq k < Nを満たす整数kと、0以上の整数xを決めて、新しく長さNの数列a'=\{a_0',\ldots,a_{N-1}'\}を次のようにして作ります。

  • a_i'= a_{i+k \mod N}\ XOR \ x

a'bと等しくなるような(k,x)の組を全て求めてください。

制約

  • 1 \leq N \leq 2 \times 10^5
  • 0 \leq a_i,b_i < 2^{30}
  • 入力中のすべての値は整数である。


解法解けませんでした。

結果

ooooo- 5完(1500点) 17:10-18:43-14:19-30:50(1WA)-46:07-xx:xx / 51:00
106位 パフォーマンス: 2250

感想

F問題、かなり難しい……。
文字列アルゴリズムも整備するべきなのかなぁ。