はじめに
AtCoder Beginner Contest 249の復習記事です。
記事におけるScanner
クラスは、自作の入力クラスです。
コンテスト
https://atcoder.jp/contests/abc249
問題A
高橋君の進む距離を考えます。
歩く+休むを1セットとすると、X
秒間にX/(A+C)
セット(端数切り捨て)できるため、距離は合計でセット数*A*B
進むことができます。
また、X
から進んだセット数を引いたあまりX%(A+C)
のうち、最大A
秒間進むこともできるため、Min(あまり,A)*B
進むことができます。
この二つを合わせた距離が高橋君の進む距離となります。
A秒間秒速Bメートルで歩き、C秒間休むことを繰り返した時のX秒後の距離
を関数にすると、F(A,B,C) = X/(A+C)*A*B + Min(X%(A+C),A)*B
に定義できます。
同様に青木君の距離を求め、どちらが長い距離を進んだかを比較して答えを求めます。
問題B
一つずつ条件を判定していきます。
C#では、char.IsUpper
関数で文字の大文字判定、char.IsLower
関数で文字の小文字判定を行うことができます。
また、全ての文字が相異なる
ということは、元の文字列の長さ=重複を除いたときの文字列の長さ
といえます。
- すべての文字をみて大文字が存在するかを判定する
- すべての文字をみて小文字が存在するかを判定する
- 元の文字列の長さ=重複を除いたときの文字列の長さが成り立つかを判定する
これらすべてが成り立っているかを判定します。
問題C
各文字列に対して使うor使わないの2択なため、2^N
個の組み合わせがあり得ます。
制約がN<=15
と少ないので、bit全探索
を行うことで全ての組み合わせを走査することができます。
s
を使用するi
の集合としたとき、s
においてi
が使われているかを判定するには、(s>>i&1)==1
で求めることができます。
そして、それぞれの組み合わせにおいて、使う文字列集合を全て走査し、文字の個数がK
個の文字の種類の最大値を求めます。
問題D
愚直に全てのi,j,k
を走査する方法では、計算量がO(N^3)
となり、A[j]*A[k]=A[i]
となるj,k
を走査する方法では、計算量がO(N^2)
となりますが、制約が1<=N<=2e5
と大きいため、実行時間制限内に処理を終わらせることができません。
そこで、あらかじめAの値の出現回数を数えておき、1<=p,q,r<=2e5
のうち、p=q*r
となるp,q,r
の組における組み合わせの個数の総和を求めます。
組み合わせの個数はpの個数 * qの個数 * rの個数
でもとめることができます。
q
を固定したとき、r
はp/q (p<=2e5)
まで走査すればよいため、計算量O(MlogM)
で求めることができます。