ABC228 参加記録
コンテスト中AC:A~D
E問題も解いたので記載しておきます。
B - Takahashi's Secret
に有向辺がある有向グラフとみなすと、これは、
・閉路がただ一つ存在する
・全ての頂点から有向辺を辿ると閉路に行き着く
というグラフとなります(こちらに私的見解で証明してみた別問題の解説記事があります)
よって、既に秘密を知っている人にぶつかるまでXから辺を辿ればよく、その時に訪問した頂点数(人数)が答えです。
C - Final Day
について、最も順位が小さくなる場合のみを考慮すればよく、それはが300点を採り、他が0点の時です。そのように考えると、他の人の点数は変わりません。
知りたいのは、となったときに、自分より大きい人が何人いるかです。
他の人の点数は変化しないので、予めAを昇順にソートしておき、より大きい人が何人いるかを二分探索で求めることができます。
Aはを含むので大丈夫なのか、心配になりますが、よりの方が必ず大きくなるので問題ありません。
計算量はソートと各iについての二分探索でです。
D - Linear Probing
クエリ1に+1ずつしていく愚直解だと、
1 1
1 1
...
1 1
という風にクエリが与えられた場合、となり間に合いません。
円環であることを一旦無視すると、が-1であるもののうち、以上で、かつであるkを見つける操作となります。
そこで、C++ならsetで、現在-1であるインデックスを記録しておきます。
すると、二分探索(lower_bound)でを探すことができ、値の削除もlog時間で可能です。
円環であることに立ち返ると、最初の探索で値が見つからなかったとき、再度1から探索をやり直せばよいです。
なお、であることから、2回目の探索で挿入位置が見つからないということはありません。
計算量は最初にsetにN個のインデックスを挿入する操作がボトルネックとなると思うので、となり間に合います。
E - Integer Sequence Fair
コンテスト中は、過去のARCのこの問題の類題であるということに囚われて、周期を見つけたいが、オイラーのトーシェント関数を求めたりやmodをとったりするやり方が、998244353は大き過ぎて適用できないからどうしよう、となってしまいました。オイラーの定理の例外ケースであるフェルマーの小定理に気づけませんでした。
長さがで要素がまでの整数列は全部で、が存在し、それぞれにまでの整数を割り当てるので、通り存在します。
が成り立ちます。
よって、を998244353-1の倍数とその余りに分ければ、
倍数部分はすべて1になるので、結局その余りのべき乗のみを考慮すればよくなります。
コンテスト後にここまで気づいて、以下のように実装してみました。
p = 998244353とします。
・とする
・とする
このように素直に実装すると、WAが4つだけ出てしまいました。この時点で公式解説を見たのですが、解決できませんでした。
他の方の実装を見るなどして調査した結果、原因が判明しました。
AtCoderライブラリや一般的な繰り返し二乗法では、として定義されます。
ここで、K = 998244352、N = 3、M = 998244353としてansを計算してみます。
rというのはあくまで、余りを計算したために生じた値であって、本来なら
を計算しているので、答えは0になるはずです。
この事態を避けるため、Mが998244353の倍数は例外として外す必要があります。