Xmas Contest 2019
Xmas Contest 2019 にご参加いただいた皆様,どうもありがとうございました!
大変遅くなりましたが解説記事が準備できました.今年も相変わらずのばたばた準備をしていましたが,いつの間にか問題がいくつも分裂してすごいことに.皆様何かしら楽しめる問題を見つけていただければ幸いです.
わたしが原案を出した問題の解説はこちらです.
それ以外の問題へのコメントはこちらです.
- A: 適当に隣接具合調べるプログラム書いた後は HTML でせっせと並べてました.1 時間くらい.
- B: これ個人的に Xmas Contest っぽさを感じる構築でよい.解くのは google ですんなり.
- F: 似て非なる問題がよくある気がするのではまりがちかもしれません.
- G: きれいな出題.
- H: writer 陣揃って data structure.
- I: 横位置を揃えて必死に DP みたいなのを考えていました.データミス申し訳ありません (clar をご確認ください).
- L: 単語リストがわかる勢ですがちゃんとプログラム書いてちゃんとはまってました.
Xmas Contest 2019 K: Set of Trees
https://atcoder.jp/contests/xmascon19/tasks/xmascon19_k
問題概要
根付き木の順序を,子を降順に並べたものの辞書順として再帰的に定める.根付き木がいくつかあって, つ選んで「小さく」するという行動ができる 人ゲームを考える.初期状態が与えられるので,先手必勝か後手必勝かゲームが無限に続くかを判定せよ.
こたえ
盤面の根付き木を とし, とします.後手が勝つ条件は「任意の根付き木 について, のうち と同型なものの個数を としたとき, である」です.そうでないときは先手が勝ちます (必ず終わります).このことを後ほど説明していきます.
実装
根付き木を整数に対応させる単射を用意すればよいです.部分木の頂点数が少ない順あるいは最大深さが小さい順などで頂点を見て,
map := 整数列から整数への連想配列 num := 0 foreach 頂点 u: v_1, ..., v_k := u の子 f(v_1) >= ... >= f(v_k) となるようにソート if [f(v_1), ..., f(v_k)] !in map: map[[f(v_1), ..., f(v_k)]] := num num += 1 f(u) := map[[f(v_1), ..., f(v_k)]]
というように f(u)
を定めていけばよいです.この問題の入力形式なら頂点番号が大きい順でも OK です.時間計算量は,次数 の頂点で なので全体で です.
根付き木に対する適切なハッシュ関数をとってもよいです.こちらなどを参照.
順序数
順序数とそれらの演算が出てきます.ある程度既知として進めるのでちゃんとやるのは他の文献に任せます.演算の定義とかはこれで行きます:
- 順序数は, と,何かの successor であるもの と,そうではないもの (limit) に分かれる.
-
- ( のとき)
- ( のとき)
- ( が limit のとき)
-
- ( のとき)
- ( のとき)
- ( が limit のとき)
-
- ( のとき)
- ( のとき)
- ( が limit のとき)
これらの演算は非可換です.
考察
不偏ゲームなので,Grundy 数を (考えられるなら) 考えたいです.局面 の Grundy 数 は, から 手で進める局面 によっては と書けないような最小の順序数です.いくつか例をやってみると (, を [
, ]
で書いています) 次のようになります.
g([]) = 0 g([[]]) = 1 g([[], []]) = 2 g([[], [], []]) = 3 g([[[]]]) = ω
[[[]]]
からは任意の非負整数に進めるので, です.
g([[[]], []]) = ω + 1
任意の自然数あるいは に進めるので, です.
g([[[]], [], []]) = ω + 2 g([[[]], [], [], []]) = ω + 3 g([[[]], [[]]]) = ω・2 g([[[]], [[]], []]) = ω・2 + 1 g([[[], []]]) = ω^2 g([[[], [], []]]) = ω^3 g([[[], [], []], [[], []], [[], []], [], [], [], []]) = ω^3 + ω^2・2 + 4 g([[[[]]]]) = ω^ω
こんな感じになるので,次のことが予想できます:根付き木 () に対し と定めると, ならば であり,また, ならば なる が存在する.
前半は, () について のときには なことを使うとできます.後半は丁寧にやると面倒なので省略するのですが,有名事実を用いて理解することができます.
すべての順序数 は を用いて という形で一意に書けます.これは Cantor 標準形と呼ばれています. ならば なので,再帰的に展開していくことでそのような順序数がちょうど根付き木に対応していて,順序数としての順序がこの問題で定めた順序と一致することがわかります.つまりこの問題は, 未満の順序数を根付き木の形で見せていただけなのでした.
順序数は整列集合なので,何をどうやってもゲームが無限に続くことはありません.よって Sprague–Grundy の定理が適用できて,盤面に根付き木 が並んでいるときの Grundy 数は となります.あとは XOR をどう計算するかだけですが, なので となり, を用いると,最初に述べたように同型なものたちごとに数えればよいことがわかります.
統計情報
正解者:TSG さん (3:03:45),kimiyuki さん (3:38:23)
コメント
Grundy 数に無限順序数が出てくる問題,ごくごく稀にある気がしますが,なかなかコンテストの問題にしづらいんですよね.Cantor 標準形が根付き木に見える→解法は同型判定だけでいい,というのが面白かったので出題してみました.
Xmas Contest 2019 J: Sub-Post Correspondence Problem
https://atcoder.jp/contests/xmascon19/tasks/xmascon19_j
問題概要
文字列 が与えられるので,ある () に対して が の連続とは限らない部分列となるようにできるか判定せよ (一応,同じ添え字は 回まで).
解法
カード 枚での解 () があれば YES でなければ NO です.なぜなら, が の部分列ならば, が の部分列であるか が の部分列であるかだからです ( と の境界に対応する場所は と の高々一方にしか入ってこないので).
のときの判定は, の文字を 文字ずつ, の中に貪欲にとっていけば線型時間でできます.
統計情報
正解者:siotouto さん (0:13:54) はじめ 95 チーム
コメント
ギャグ枠です. はフェイクです.
Post の対応問題は決定不能な問題の中でもパズルっぽい見た目ということで人気があります (?).問題設定を少し変えた亜種は結構研究されているらしく,決定不能と決定可能の間が見えてくるのが面白いですね.
Xmas Contest 2019 E: Sum of f(n) 解説
https://atcoder.jp/contests/xmascon19/tasks/xmascon19_e
問題概要
の素因数の個数 (重複込み) を とする. が与えられるので を求めよ.
解法 1 (?)
答えを手元で全部計算して,適当な間隔で区切って埋め込みます.狭い区間については区間篩のアルゴリズムで を効率的に計算できる (素数 で篩うときに で割り切れる回数だけ を足す) ので,これで正解することができます.
終わる確信があったら,手元で D 問題と一緒に計算するとよいと思います! D 問題より桁数が多かったり時間制限が短かったりでちょっとだけ大変かもしれません.
解法 2
素数 の影響が何回足されるかを考えると,各 について, 以下の の倍数の個数, の倍数の個数, の倍数の個数,……を足していけば答えになります. 以降の倍数が現れるのは なもののみなので,それらについてはひとつずつ処理できます.これで,あとは を求めればよくなりました.
の値は 通りくらいしかないので,同じ値になる部分をまとめて計算したいです. なので,「 以下の素数の個数」という形のものが数えられれば, と計算できます ( は 以下の素数の個数).
これは,賢い DP をするとできます.素数を小さい順に とします. を, 以下の正の整数であって のいずれでも割り切れないものの個数とおきます. という漸化式が成り立ちます. なので, の形のものを計算するのに必要な はやはり の形をしています.
このままだとまだ遅いので高速化します. から への変化に注目すると, では変わらず, では 減るだけになっています.ということをふまえて とおき直すと, では , では となります.これで DP 配列を使い回して の部分のみ更新すればよいことになります.なお, は 以下の正の整数に対して Eratosthenes の篩で を処理したときに残るものの個数になっています.
時間計算量を見積もると,更新箇所の個数が
- についてそれぞれ 個
- について合計で 個
となり (素数の密度についての定理を用いました) 全体で 時間となります.これで 点がとれます.
なお,素数の個数 の計算については,より高速なアルゴリズムも知られています.
統計情報
45 点:1 チーム
100 点:team_2019 さん (29:26) はじめ 7 チーム
コメント
実は冒頭のストーリーは結構実話に近く,D 問題を提案しようとしたら書き間違えて,わたしが気づかないまま snuke さんが解いてくれて答えの大きさを見て気づいてわたしも解きました.高速素数カウントは初めて実装したので勉強になりました!
Xmas Contest 2019 D: Sum of (-1)^f(n) 解説
https://atcoder.jp/contests/xmascon19/tasks/xmascon19_d
問題概要
の素因数の個数 (重複込み) を とする. が与えられるので を求めよ.
解法 1 (?)
答えを手元で全部計算して,適当な間隔で区切って埋め込みます.狭い区間については区間篩のアルゴリズムで を効率的に計算できる (素数 で篩うときに で割り切れる回数だけ 倍する) ので,これで正解することができます.
点は割と易しめだと思います. 点は結構な計算資源を使うかなと思っていたので,解けちゃってもいいかなという感じでした.何なら昔の問題にリンクを貼っていて,パソコンを使いましょうというのを伝えていた感じだったかもしれません.
解法 2
とおきます.突然ですが,正の整数 に対し, は が平方数のとき ,そうでないとき です.理由は例えば なら
3^0 3^1 3^2 3^3 2^0 +1 -1 +1 -1 2^1 -1 +1 -1 +1 2^2 +1 -1 +1 -1
みたいな感じで多次元の格子点を市松模様で塗るのを考えてみるとわかります. は Liouville 関数として知られていて,Wikipedia にもこの式は載っています.もうちょっと突然でない導き方については後述します.
さて, を求めたいわけですが, みたいなのを見たら累積和をとるという知る人ぞ知る典型テクニックがありまして, となります ( を先に固定して和をとるとわかります).一方 が平方数なら というのを で和をとると なので, が得られました.これを と書くと の漸化式を得たことになります.
この形の漸化式をどうするかも知る人ぞ知る典型テクニックなのですが, を計算するのに必要な の値は の形だけになっていて ( に注意),異なる の値は 通りくらいしかありません. の計算は同じ の値のものをまとめることで 時間でできるので,
- について を求めるのに 時間
- について を求めるのに 時間
となり,全体で 時間の解法が得られました.実装によりますが 点の想定です.メモ化再帰で連想配列の類を使うと実行時間がちょっと厳しいかもしれません (配列 つでできます).
さらなる高速化ですが,小さい方の答えを定義に戻って計算します.Eratosthenes の篩を用いると について を求めるのが 時間でできます.大きい方は まででよくなって 時間になるので, くらいにとるのがよく, 時間解法が得られました (高速な篩を用いれば 時間).これで 点です.
Dirichlet 級数
最初に天下った部分の話です. は乗法的関数なので,(形式的) Dirichlet 級数を考えてみたくなりますね! Euler 積の形で計算すると, となり Riemann の 関数で表すことができました. をかけるという操作は をとることに対応していて, は平方数だけ な級数を表しているので,先ほど使った式が示せました.この辺の話は,例えば maspy さんの HP で丁寧に解説されています.
さっきやった方法は Liouville 関数に限った話ではなく,累積和が簡単に書けている数論的関数を で割ったもの (つまり,Möbius 変換したもの) の累積和を高速に求める一般的な手法になっています.なので,Möbius 関数 や Euler の 関数なんかの累積和も同様に高速に求まります (それらのほうがたぶん有名なので, の累積和に帰着させて解くという方針も見られました).
統計情報
45 点:3 チーム
100 点:chocorusk さん (1:00:49) はじめ 6 チーム
コメント
Project Euler の回し者ですか? はい…….数学寄りの問題が集まっているサイトですが,この手の sublinear algorithm の数論問題もたくさんあります.解法共有は正解者のみという文化なので,皆さんもぜひ頭 and/or パソコンを駆使して問題を解いていきましょう.
テストデータには,制約内で答えが最大になる が (無意味に) 入っています.この関数の漸近的な振る舞いは,かなり謎に満ちてますね…….
Xmas Contest 2019 C: Sokoban 解説
https://atcoder.jp/contests/xmascon19/tasks/xmascon19_c
問題概要
倉庫番の盤面が与えられるので (入力公開),解くのに必要な最小手数を求めよ.
sample, 01, 02
小さいので,手で遊んで解けます.しかし,解くだけなら簡単ですが最小手数は非自明だったりします.コンテストでは,見つかった解から 手ずつ減らして提出してみるのもありだと思います.
確実なプログラミング解ももちろん可能で,盤面の状態数を考えてみると,たとえば 02 ではうさぎの位置は 通り,そのそれぞれに対し箱の位置が 通り,と抑えられて,特に枝刈り等せずとも BFS で最小手数を求めることができます.
01 は,解くだけなら本当に簡単なのを適当に作ってみました. 手の解がとても見えやすいと思いますが,うまいことやると減って不思議です.
02 は,左上の空間を利用できる問題を作ってみました (パズルとしての問題ならよくありそう).左上に何度も行くのをやめるのが大事でそれをすると 手の解が見えやすいと思うのですが,やっぱりうまいことやると減って,よくわかりません…….ちなみに最後に片づく荷物が左上か右下しかありえないので,奇数手であることがわかって提出を少し節約できたりします.
03
荷物が壁の直角の隅に置かれてしまうと,そこがゴールでない限り詰んでしまいます.このことから,入力にたくさん現れる
########### ####....### ...#.##.... ##.@..##### ###...##### ###########
という部分が一方通行の役割を果たすことがわかります (上の図の向きでは左から右へのみ,一定の手数で,荷物の位置を変えずに通れます).入力の右下の荷物を片付けに行けばよいので, の部屋のようなものを頂点とした最短路問題として解くことができます.
04
列ごとに
########### ########... ##...##.@.. #.@..##.#.# ..#.###.#.. #.#.@.@..## #..#...#.## ##.#.....## #.@####.#.. #....##..@. #..#...##.. ###..#.##@. ##.@##..... ##....###.. ##..#.##### #####.##### ........... ###########
というパターンが繰り返される構造になっています.左から右へ抜けたいのですが,そのためには右下を回って箱を一度ずらす必要があり,そうすると一旦下から出て一番左まで戻らないといけません.よって,右から 番目のブロックを左から右へ抜けるためには 回来なければならない,そのそれぞれに対して右から 番目のブロックを左から右へ抜けるために 回ずつ, 回来なければならない,そのそれぞれに対して……,というようにして,右から 番目のブロックに 回来なければなりません.これに,各ブロックでかかる手数 (手で遊んで数えるのがよいと思います) を掛けて足すことで答えが求まります.
この入力は,盤のサイズに対して指数手数かかる例になっています.手でクリアしようとすると絶望を感じられると思います.
05
03 で使われていた一方通行のパターンが荷物が片付いていない状態で登場しています.左上の部分は最後に訪れないといけないので,グラフの問題で言い換えると「すべての辺を少なくとも 回通ってスタート位置に戻ってくるための最小コスト」を求める問題になっています.
これは,(有向) 中国人郵便配達問題として知られた問題です.辺を通る回数分増やして考えると,すべての辺をちょうど 回ずつ通ってスタート位置に戻って来られる条件は (グラフが強連結かつ) すべての頂点の出次数と入次数が等しいことです (Euler circuit).ということで,最初のグラフに辺を足して出次数と入次数を等しくする問題と言い換えられますが,その最小コストは入次数が余っている点から出次数が余っている辺へ流す最小費用流問題を解くことで求めることができます.
omake
html にのみ入っているこのデータ,パズルガチ勢であるところのすぬけさんが作りました.最短手数の証明が怪しくて出題を見送ったのですが,参加者の方によってすごく縮められていて,こわいです.わたしは,解けません.
統計情報
得点 01 02 03 04 05 人数 100 o o o o o 1 60 o o o o 7 43 o o o 8 35 o o o 6 18 o o 39 11 o 5 7 o 53
正解者:DEGwer さん (2:39:03)
コメント
倉庫番の盤面が与えられたとき解の有無を判定する問題は PSPACE 完全であることが知られています.倉庫番のパーツを作って Turing machine をエミュレートするという証明です.この論文の見どころは,平面交差です.
そんなわけで実質任意の決定可能問題は倉庫番で表せるのですが,自然なのはグラフの問題で,その中でコンテストであまり頻繁には見かけない (気がする) 郵便配達が思いついたので出してみたくてこのような形になったのでした.
無限直積の双対加群こわい
概要・参考文献
を示します.
https://mathoverflow.net/q/10239 ←これを読み解いたよというような話です.
何がすごいの?
は簡単です.直和の普遍性と,同一視 ですね.こっちは を任意の単位的可換環にしても成り立ちます.一方,直積からの準同型というのは,なんだかよくわからないものです.
また, じゃなくて体 だったら様子が異なってきます.無限次元線型空間の双対をとると次元が真に大きくなることが知られていて, です.
体だったら基底がとれるので双対をとれば単に大きくなるところが, だと直積からの準同型というのが意外ときつい制約で,小さくなってなぜかちょうど直和くらいになってしまう.そんな不思議な定理です.
証明の流れ
準同型 を ( は第 成分だけ で他が のやつ) で定めたとき,
- が単射であること
- であること
を示します.この 1. は当たり前と思いきやそうではなくて,各 に対して を決めたからといって とはできない (有限和になってない!) のが罠です.直積の厄介なところですね.
1. 単射性
,つまり任意の に対して であることを仮定して, を示す.
任意の をとる.各 について, と は互いに素なので, となる がとれる.
任意の に対して, なので,仮定より .よって .
同様に なので,.以上で が示せた.
これは, の「PID だが局所環ではない」という性質を使っています.体でない局所環で反例が作れるかは,よくわかりません…….
2. 像が直和に入ること
任意に をとったとき,,つまり のうち有限個を除いて となることを示す.
を, かつ (整除) かつ任意の で が成り立つようにとれる (順番に,十分大きい倍数をとっていけばよい).
任意の について, なので, とおくと となる.すると三角不等式と のとり方より が成り立つ.ここで,十分大きい では なので である.
なので,十分大きい では となり,示すべきことが得られた.
お気持ちとしては,「めっちゃ増えてくような無限列も有限値に送らないといけないので,それっぽい列をとれば後ろの方の影響があってはならないことが言える」みたいな感じです.
mathoverflow にリンクが貼られている http://www-users.mat.umk.pl/~gregbob/seminars/2008.11.07b.pdf では不等式評価を用いずに,こちらも局所環でない PID について示そうとしているのですが,PDF でいう のところが間違っています ( が ではなく なので). の場合なら とか とか好きに決められるので簡単に直せるのですが,一般にはダメそうです.上手く修正できる気もしますがあまり考えていません.
コメント
無限直和とか無限直積とかはやっぱりこわいですが,好きな定理上位にランクインしました.
間違いを見つけた方は是非教えてください.