キャディプログラミングコンテスト2021(AtCoder Beginner Contest 193)解法メモ(全問題)
タイトルが長すぎる
リアルタイムで参加できなかったコンテストのブログが抜けてて気になったので、暇なときに解き直してブログを書くことにしました。
A - Discount
算数。割合の計算は比を使った式で書くとわかりやすいと個人的に思う。
と考えてもいいし、
と考えてもいい。どちらにせよ
という式になる。比を使った式の好きなところはこういうところ。
何パーセント引きか聞かれているので、が答え。計算量は。
B - Play Snuke
1軒しかお店が無いとする。このとき、分かけてお店に着いた時、スヌケマシンの在庫はである。在庫が以上のとき、つまりが以上のときに限り円でスヌケマシンを買うことができる。
お店が軒に増えた場合でも各店舗での購入条件と購入金額はかわらない。また、どのお店を選んでも、その選択が影響することはないので、スヌケマシンを買うことができるお店のうち一番安く買えるお店での購入金額を求めればよい。計算量は。
C - Unexpressed
事象とその余事象の和は全事象である。
「と表せないもの」 = 「全体」 「と表せるもの」
なので、「と表せるもの」の個数をカウントする。
「と表せるもの」の個数を上から評価する(最大値を見積もる)。
を固定したとき、を増やすとも増加する。よって、を満たすの個数はである。
に注意すると、は最大で程度まで大きくなるので、全体の個数としては程度となる。(上から評価しているので、として計算した。)
この値はのときでもおよそであるため、の組を全探索しても実行時間制限に間に合うことがわかった。
カウントするときは重複やオーバーフローに注意して実装する。重複を避けるにはC++のsetなどを用いる。で探索を打ち切る処理を忘れるとTLEするので注意。計算量は。
D - Poker
かなり考えることが多いので順を追って考察する。
まず、「高橋君の勝つ確率」はで求められる。ここで言う「すべてのパターン」とは、すでに表向きになっていて裏向きのカードとして選ばれることのない枚を除いた枚から枚(高橋君の裏向きのカード枚と青木君の裏向きのカード枚)を選ぶ方法を指す。よって分母はとなる。
高橋君に配られた裏向きのカードを、青木君に配られた裏向きのカードをと置く。高橋君が勝つパターンの数をカウントしたい。裏向きのカードが何の数かわかれば手札の点数を求めることができるが、ここで枚の中から枚選ぶような全探索をするとの計算量となってしまうので実行時間制限に間に合わない。しかし、の組み合わせとしては通りしかないので、とを決めたときが選ばれるのは何通りか求められれば、高橋君が勝つパターンの数も高速に求められる。
整数が書かれたカードの残り枚数をとする。なら、枚の中から枚選ぶので通りである。なら、枚の中から枚、枚の中から枚それぞれ選ぶので通りである。高橋君の手札の点数が青木君の手札の点数より高い場合にこの通り数をそのままカウントに加えることで、確率を求めることができる。
計算量は、手札の枚数を、カードに書かれた整数の種類数をとして。この問題ではであるため十分高速に動作する。
E - Oversleeping
電車の停止する区間は周期的に訪れ、上で一定である。高橋君の起きる区間も同様に、上で一定である。
ここで、中国剰余定理(CRT)を活用する。この定理は、
「で割ると余り、で割ると余る整数は上にちょうど1つだけ存在する」
ということを言っている。さらに、この解となる整数を構成する効率的なアルゴリズムが知られていて、で動作する。実装には拡張ユークリッドの互除法を用いることが多いが、atcoder libraryに実装されているcrt
をそのまま用いることもできる。
制約より、とが小さいことがわかる。よって、電車が停止してから秒後のタイミングと、高橋君が起きてから秒後のタイミングが初めて一致するときがいくつか求め、の組を全探索して最小値を求めればよい。具体的には、以下の2つの合同式を同時に満たす解の最小値を、の範囲で全探索する。
計算量は、。
F - Zebraness
まだ解けていないが、工夫することでフローの問題に帰着できるらしい。
感想
はじめてCRTを学んだが、そこまで難しくなくて食わず嫌いしていたなーと思った。ちなみにCRTは条件式が3本以上あっても解を求めることができる。