ABC215 参加記録
B - log2(N)
GCCの組み込み関数__builtin_clzllを使うと、
__builtin_clzll(1LL) - __builtin_clzll(N)
で求められます。
提出コード:https://atcoder.jp/contests/abc215/submissions/25200114
C - One More aab aba baa
文字列の並び替えの総数は最大でも、8! = 40320なので全列挙可能です。
c++ではnext_permutationで順列全探索できます。得られた文字列を昇順ソートして重複要素を削除し、K番目を求めます。
提出コード:https://atcoder.jp/contests/abc215/submissions/25208141
D - Coprime 2
条件のを言い換えると、「kはと共通する素因数を持たない」です。よって、の素因数を全て列挙し、素因数の倍数を全て候補から外し、残ったM以下の数が答えです。
Nが小さいので高速素因数分解により、全ての素因数はで全列挙可能です。自作ライブラリになかったので、コンテスト中の実装は下記のサイトのものを使用しました。
エラトステネスのふるいと高速素因数分解 – Manuel1024の引きこもルーム
高速素因数分解は過去問にもありましたが、osa_k法と呼ぶのは初めて知りました。
素因数の倍数を候補から外す処理は、エラトステネスの篩と同様の処理でできます。候補となる素因数の個数をPとして、くらいです。
下記のコードは、osa_k法をオリジナルで実装しなおして、コンテスト後に提出し直したものです。
提出コード:https://atcoder.jp/contests/abc215/submissions/25263829
E - Chain Contestant
コンテスト後に解説は見ずにACしました。
状態として必要なのは、
1.これまでどのコンテストにでたか
2.最後にどのコンテストにでたか
です。1はの冪集合で表現でき、2は10通りです。
1回目のコンテストから順に、i回目のコンテストに出る、出ないという選択に基づいて、各状態を更新する場合、全状態数は最大でもなので、実行時間制限に間に合います
dp[i][j][k] := i回目のコンテストまでを考えた時に、出場したコンテストの集合がjで、最後に出場したコンテストがkであるものの総数
とします。また、A = 0, B = 1, ..., J = 9とします。
ここで、初期状態をdp[0][0][0] = 1にしておきます。空集合を定義していないので状態と矛盾しますが、特に実装上問題ありません。
i回目のコンテストから回目のコンテストへの状態遷移は以下のようになります。
(1)回目のコンテストに参加しない
出場したコンテストや最後に出場したコンテストの状態に関わらず、状態はからに引き継がれます。よって、
+=
(2) 回目のコンテストに参加する
(i) でが出場済みとなっている時(がを含む)
(A) 最後に出場したコンテストがの時( == )
に出場可能です。よって、
+=
(B) 最後に参加したコンテストがでない時( != )
問題文の条件に反するので、遷移できません。
(ii) でが出場済みとなっていない時(がを含まない)
最後に出場したコンテストによらず、コンテストに出場できます。よって、
+=
最後にdp[N][0000000001〜1111111111][0〜9]の総和をとれば答えです。
コンテスト中、全状態数をしっかり見積もらずに棄却してしまったので、10種類という少ない制約からも、もう少し考えるべきでした。
提出コード:https://atcoder.jp/contests/abc215/submissions/25289175