Loading [MathJax]/jax/output/CommonHTML/jax.js

デンソークリエイトプログラミングコンテスト2024(AtCoder Beginner Contest 361)F,G問題メモ

デンソークリエイトプログラミングコンテスト2024(AtCoder Beginner Contest 361)

361=19×19 なだけあって、囲碁に関する問題が数問あった。

F - x = a^b

問題文

  • 1 以上 N 以下の正整数 x であって、ある正整数 a2 以上の 正整数 b を用いて x=ab と表現できるものはいくつありますか?

制約

  • 1N1018

解法

メビウス関数を知っていれば楽に解ける問題。

b を決めれば、a=1bN が全て条件を満たすので、 基本的な方針としては、様々な b に対して bN を足し合わせたものが答えとなる。
(以降、単に bN で、bN を指すとする)

b として取り得る値は、260>1018 より、259 を考えればよい。

また 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 でも表せるので、 2N + 3N - 6N とすれば重複を除けることになる。

このような事をするのに便利なのが、メビウス関数(を、約数系包除原理用にカスタマイズしたもの)である。

これで、59b=2˜μ(b)×bN が答えとなる。

(なんか、1だけずれるので、微調整したら通る)

Python3

解法2

ご丁寧に、サンプルに N が最大の 1018 のときがあって、答えは 109+106+α 程度である。

このうち a2 と表せる数が 109 個あるので、残りは 106+α 個程度である。

つまり、3 以上の素数の b と、bN 以下の a について、 素直に ab を計算して set(重複しない集合を表現するデータ構造)に放り込んでいっても、 対象は 106 個程度であり、TLEやMLEにはならないことがわかる。

重複除外はsetの機能に任せてよくなり、(最終的なsetのサイズ + 2N)が答えとなる。

ただし、a=c2 と表現されるような a は、2N の方で数えられているので、a が平方数の場合は除外する。

G - Go Territory

問題文

  • 2 次元平面上に N 個の石が置かれています。i 番目の石は座標 (Xi,Yi) にあります。石は全て第一象限(軸上含む)の格子点にあります。
  • 石の置かれていない格子点 (x,y) であって、石に囲われているものの個数を求めてください。
    • つまり、上下左右のいずれかに 1 移動することを繰り返すことで、石の置かれている座標を通らずに (1,1) に到達することができない (x,y) の個数を求めてください。

制約

  • 0N2×105
  • 0Xi,Yi2×105
  • (Xi,Yi) は相異なる

解法

ひたすら泥臭く頑張ればできるのはできるんだけど、なかなか上手く実装するのが難しい問題。

公式Editorialを自分用にメモしただけ。なるほど!この発想は気がつかなかった。

「石の置かれていない格子点」を空格子点とする。

この問題は、愚直には、範囲内の隣り合う空格子点同士をUnion-Findで結ぶなどすることで、 外 (1,1) と同じグループにならない空格子点の個数を数えればよい。
ただ、O(XmaxYmax) の頂点ができるので、TLEとなる。

考慮する空格子点を石の周囲最大8つに限定すると、石により分断されているかの判定ができる情報量を保ったまま、頂点数を O(N) とできる。
しかし、どっちが内か外かの判定や、入れ子構造になった場合を見つけて除外するのに、地道な実装が必要となる。(公式Editorial 1つめの解法)

Union-Find上の頂点数を減らすもう1つの方法として、 互いに行き来できることが明らかな空格子点のカタマリは、まとめてやることが考えられる。

具体的には、横に連続する空格子点のカタマリは、1つの頂点としてまとめる。

|-----------------------------
|--|■■■■■||■■|---------
||■|--------|■|--|■|-------
||■|----------------|■|-----
||■|--|■■|------|■|-------
|--|■■|--|■■■■|---------
|-----------------------------

こうすると、頂点数は O(Xmax+N) に抑えられ、愚直とほぼ同じ解法が使える。
入れ子構造とかも考えなくて済み、楽に実装できる。

外周に1個分、確実に空格子点である列を作る必要がある点に注意。

Python3

programming_algorithm/contest_history/atcoder/2024/0706_abc361.txt · 最終更新: 2024/07/10 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0