−目次
デンソークリエイトプログラミングコンテスト2024(AtCoder Beginner Contest 361)F,G問題メモ
デンソークリエイトプログラミングコンテスト2024(AtCoder Beginner Contest 361)
361=19×19 なだけあって、囲碁に関する問題が数問あった。
F - x = a^b
問題文
- 1 以上 N 以下の正整数 x であって、ある正整数 a と 2 以上の 正整数 b を用いて x=ab と表現できるものはいくつありますか?
制約
- 1≤N≤1018
解法
メビウス関数を知っていれば楽に解ける問題。
b を決めれば、a=1~⌊b√N⌋ が全て条件を満たすので、
基本的な方針としては、様々な b に対して ⌊b√N⌋ を足し合わせたものが答えとなる。
(以降、単に b√N で、⌊b√N⌋ を指すとする)
b として取り得る値は、260>1018 より、2~59 を考えればよい。
また b が素数で無い場合、b=kb′ と2数の積に分解できるとして、 ab=(ak)b′ と、より小さい指数による表現ができてしまうので b は素数のみ考えればよい。
重複除去
しかし、43=82=64 など、異なる (a,b) が同じ x になってしまうことがある。
これは、(22)3=(23)2 のように、a 自体が cd と表せる場合に発生しうる。
b=2 でも b=3 でも表せてしまう数は、b=6 でも表せるので、 2√N + 3√N - 6√N とすれば重複を除けることになる。
このような事をするのに便利なのが、メビウス関数(を、約数系包除原理用にカスタマイズしたもの)である。
これで、59∑b=2˜μ(b)×b√N が答えとなる。
(なんか、1だけずれるので、微調整したら通る)
解法2
ご丁寧に、サンプルに N が最大の 1018 のときがあって、答えは 109+106+α 程度である。
このうち a2 と表せる数が 109 個あるので、残りは 106+α 個程度である。
つまり、3 以上の素数の b と、b√N 以下の a について、 素直に ab を計算して set(重複しない集合を表現するデータ構造)に放り込んでいっても、 対象は 106 個程度であり、TLEやMLEにはならないことがわかる。
重複除外はsetの機能に任せてよくなり、(最終的なsetのサイズ + 2√N)が答えとなる。
ただし、a=c2 と表現されるような a は、2√N の方で数えられているので、a が平方数の場合は除外する。
G - Go Territory
問題文
- 2 次元平面上に N 個の石が置かれています。i 番目の石は座標 (Xi,Yi) にあります。石は全て第一象限(軸上含む)の格子点にあります。
- 石の置かれていない格子点 (x,y) であって、石に囲われているものの個数を求めてください。
- つまり、上下左右のいずれかに 1 移動することを繰り返すことで、石の置かれている座標を通らずに (−1,−1) に到達することができない (x,y) の個数を求めてください。
制約
- 0≤N≤2×105
- 0≤Xi,Yi≤2×105
- (Xi,Yi) は相異なる
解法
ひたすら泥臭く頑張ればできるのはできるんだけど、なかなか上手く実装するのが難しい問題。
公式Editorialを自分用にメモしただけ。なるほど!この発想は気がつかなかった。
「石の置かれていない格子点」を空格子点とする。
この問題は、愚直には、範囲内の隣り合う空格子点同士をUnion-Findで結ぶなどすることで、
外 (−1,−1) と同じグループにならない空格子点の個数を数えればよい。
ただ、O(XmaxYmax) の頂点ができるので、TLEとなる。
考慮する空格子点を石の周囲最大8つに限定すると、石により分断されているかの判定ができる情報量を保ったまま、頂点数を O(N) とできる。
しかし、どっちが内か外かの判定や、入れ子構造になった場合を見つけて除外するのに、地道な実装が必要となる。(公式Editorial 1つめの解法)
Union-Find上の頂点数を減らすもう1つの方法として、 互いに行き来できることが明らかな空格子点のカタマリは、まとめてやることが考えられる。
具体的には、横に連続する空格子点のカタマリは、1つの頂点としてまとめる。
|----------------------------- |--|■■■■■||■■|--------- ||■|--------|■|--|■|------- ||■|----------------|■|----- ||■|--|■■|------|■|------- |--|■■|--|■■■■|--------- |-----------------------------
こうすると、頂点数は O(Xmax+N) に抑えられ、愚直とほぼ同じ解法が使える。
入れ子構造とかも考えなくて済み、楽に実装できる。
外周に1個分、確実に空格子点である列を作る必要がある点に注意。