2021年11月16日火曜日

ABC 226 F - Score of Permutations

F(M)=F(M) =長さNNの順列で、すべてのサイクルの長さがMMの約数であるようなものの数 f(m)=f(m)=長さNNの順列で、サイクルの長さのLCMがmmであるようなものの数

とするとき、求める数はNNの分割のLCMとして得られるようなすべてのmmについてf(m)mKf(m)m^Kの総和を取ったものに等しい。

F(M)=mMf(m)F(M) = \sum_{m | M} f(m)であり、ffFFのメビウス反転として計算できる。また、NNの分割のLCMの最大値はランダウ関数g(N)g(N)として知られていて、OEISによるとg(50)=180180g(50) = 180180なので、個々のF(M)F(M)を高速に計算できればよさそう。

F(M)F(M)は単純なDPで求まる。dp[x]=1,2,...,N\operatorname{dp}[x] = 1, 2, ..., Nからxx個使って任意個数の長さがMMの約数であるようなサイクルを作る場合の数、とするとき、MMの各約数m(N)m ( \le N)について

dp[x+m]+=(m1)!(Nx1m1)dp[x] \operatorname{dp}[x+m] \mathrm{{+}{=}} (m-1)! \binom{N-x-1}{m-1}\operatorname{dp}[x]

と遷移すればよい。(m1)!(m-1)!は長さmmのサイクルの総数であり、(Nx1m1)\binom{N-x-1}{m-1}はまだ使っていないNxN-x個の数から(完全な数え上げをするために)必ず最小の数は選ぶとして残りのm1m-1個を自由に選ぶことに対応している。計算量はO((N2+logK)g(N)){O}((N^2 +\log K)g(N))[1]

また、FPSで考えることもできる。MMの約数だけに限って各長さのサイクルの総数を数えたEGFをDM(x)\mathcal D_M(x)とするとき、DM(x)=mM(m1)!xm/m!=mMxm/m\mathcal D_M(x)=\sum_{m | M}(m-1)!x^m/m! = \sum_{m|M}x^m/mである。このとき、F(M)=[xN/N!]exp(DM(x))F(M) = [x^N/N!]\exp(\mathcal D_M(x))である。[2] FFTを使うと計算量はO((NlogN+logK)g(N)){O}((N\log N + \log K) g(N))


解説を見ると、LCMごとにまとめなくてもすべての分割を試せるらしい。確かに。


  1. 実際には1,2,...,g(N)1, 2, ..., g(N)の約数でNN以下であるものの総数が問題になる。これがo(N2){o}(N^2)であればもっとよい評価ができることになるけれど、よくわからなかった。 ↩︎

  2. 仮に「箱」が区別できる設定だったら単にEGFの掛け算をすればいいので[xn/n!]n1DM(x)n[x^n/n!]\sum_{n \ge 1}\mathcal D_M(x)^nでよくて、箱の区別を無くすために各項をn!n!で割るとn1DM(x)n/n!=exp(DM(x))\sum_{n \ge 1}\mathcal D_M(x)^n/n! = \exp(\mathcal D_M(x))になる。 ↩︎

2021年11月9日火曜日

ACL Beginner Contest F - Heights and Pairs

hih_iが互いに異なる場合は(2N1)!!=(2N)!/2NN!(2N-1)!! = (2N)! / 2^N N!通りという有名事実がある(後述)。以下、pi=(2i1)!!p_i = (2i-1)!!とする。

身長hhの人がaha_h人いるとする。ii人の同じ身長を持つ人からjjペアを作る場合の数は(i2j)pj\binom{i}{2j}p_jである。F(x)=hj(ah2j)pjxjF(x) = \prod_h \sum_j \binom{a_h}{2j}p_j x^{j}とすると、F(x)F(x)xkx^kの係数[xk]F(x)[x^k]F(x)2N2N人から身長が同じであるようなkkペアを作る場合の数に等しい。このとき、残った人、つまり2(Nk)2(N-k)人でペアを作る場合の数はpNkp_{N-k}通りであり、あとは包除でk(1)kpNk([xk]F(x))\sum_k(-1)^kp_{N-k}([x^k]F(x))通りと求まる。

(2N1)!!(2N-1)!!について

2N2N人に1,2,...,2N1, 2, ..., 2Nという番号を振ってこの順に並べ、二人ずつ取り除いていくとする。この際、ペアのうちの一人目は必ずその時点で番号が最小の人を選ぶ、としておくと完全な数え上げができる。一人目には2N12N-1通りの人がマッチできて、二人目には2N32N-3通りの人がマッチできて、……となるので二重階乗の記号を使うと(2N1)!!(2N-1)!!と表せる。

別の考え方もできる。2N2N人を自由な順番で一列に並べて、隣り合う二人をくっつけてNNペアを作ることにする。並べ方は(2N)!(2N)!通りあるが、二人組の内の順番は考慮しないので2N2^Nで割る必要がある。さらに、NNペアの順番も考慮しないのでN!N!で割って(2N)!/(2NN!)(2N)!/(2^N N!)と求まる。これらは二重階乗の公式も与えている:

(2N1)!!=(2N)!2NN! (2N-1)!! = \frac{(2N)!}{2^N N!}

2021年11月7日日曜日

エイシング プログラミングコンテスト 2020 F - Two Snuke

2(s1+n1+u1+k1+e1)+Δs+Δn+Δu+Δk+ΔeN2(s_1+n_1+u_1+k_1+e_1)+\Delta s + \Delta n + \Delta u + \Delta k + \Delta e \le Nで各変数は非負という条件下でΔsΔnΔuΔkΔe\Delta s\Delta n\Delta u\Delta k\Delta eの総和を取る問題。

d=N(Δs+Δn+Δu+Δk+Δe)d = N - (\Delta s + \Delta n + \Delta u + \Delta k + \Delta e )とするとき、ΔsΔnΔuΔkΔe\Delta s\Delta n\Delta u\Delta k\Delta es1+n1+u1+k1+e1d/2s_1+n_1+u_1+k_1+e_1 \le d/2の非負整数解の数だけ足される。これは(d/2)+55)\binom{\lfloor d/2 \rfloor)+5}{5}通りだから、求める数は

d1+d2+d3+d4+d5+d=N(d/2+55)d1d2d3d4d5 \sum_{d_1+d_2+d_3+d_4+d_5 + d = N}\binom{\lfloor d/2 \rfloor+5}{5}d_1d_2d_3d_4d_5

に等しい。FPSで考えるなら、nnxn=x/(1x)2\sum_n nx^n = x/(1-x)^2を5乗してi(i/2+55)xi\sum_{i} \binom{\lfloor i/2 \rfloor +5}{5}x^{i}という謎の級数を掛けると、xNx^Nの係数が求める数である。後者にBerlekamp-Massey法を適用してみると21次の多項式を分母とする有理式が出てくるので、xNx^Nの係数はBostan-Mori法で求まる。


そもそも一般にi/2\lfloor i/2 \rfloorの多項式を係数にするFPSが有理べき級数になるのかどうかとか、基本的なことがよくわかっていなかった。

与えられたFPSf(x)f(x)の偶数項、奇数項がそれぞれ有理べき級数g(x),h(x)g(x), h(x)の偶数項、奇数項と一致しているなら、ggの(0-basedで)偶数項だけ抜き出したもの(g(x)+g(x))/2(g(x)+g(-x))/2hhの奇数項だけ抜き出したもの(h(x)h(x))/2(h(x)-h(-x))/2を足せばf(x)f(x)になるので、確かに有理べき級数になる。一般にi/k\lfloor i/k \rfloorの多項式を係数とするFPSについても、11kk乗根を考えれば同じことが言える。

一般化すると、次の性質を満たすf(x)=nanxnf(x) = \sum_n a_n x^nは有理べき級数と言える:

MM個の有理べき級数fk(x)=nbk,nxn (k=0,1,...,M1)f_k(x) = \sum_n b_{k, n}x^n \ (k=0, 1, ..., M-1)NNN \in \mathbb Nが存在して、nNn \ge Nならばan=bnmodM,na_n = b_{n \bmod M, n}

2021年10月30日土曜日

HackerEarth - Connected Permutations

求める数をana_nとする。長さnnの順列を先頭kk要素が1,2,...,k1, 2, ..., kの順列であるような最小のkkで分類して数えると、それぞれak(nk)!a_k(n-k)!通りある。長さnnの順列から長さn+1n+1の順列を作ることを考えると、n+1n+1kk箇所に挿入可能なのでan+1=k=1nkak(nk)!=k=0nkak(nk)!a_{n+1} =\sum_{k=1}^{n}ka_k(n-k)! = \sum_{k=0}^nka_k(n-k)!a0=0,a1=1a_0=0, a_1=1としてオンラインFFTするとO(Nlog2N){O}(N \log^2 N)で解ける。

2021年10月20日水曜日

CodeChef SnackDown 2021 Online Qualifiers - Minimise Difference

問題: 無向グラフが与えられる。出次数の最大値が最小であるようなacyclic orientationを求めよ。

出次数がDD以下であるacyclic orientationが存在するかどうかの判定問題が解ければよい。判定問題は次のように解ける:

まだ選んでいない頂点の中でトポロジカル順序で先頭にする頂点vvを自由に選ぶ。このvvの次数はDD以下でなければならず、そのような頂点が存在しなければ判定はNOである。存在する場合、vvから伸びているすべての辺を削除する。以上を頂点の数だけ繰り返す。実装はキューでO(N){O}(N)でできる。

2021年10月9日土曜日

エクサウィザーズプログラミングコンテスト2021 (ABC 222) G - 222

与えられた数列を(ai)i=0 (a0=0,a1=2,a2=22,...)(a_i)_{i = 0}^\infty \ (a_0=0, a_1 = 2, a_2 = 22, ...)とする。M=[10201],v=[01]M = \begin{bmatrix} 10 & 2 \\ 0 & 1\end{bmatrix}, v= \begin{bmatrix} 0 \\ 1\end{bmatrix}とするとき、aka_kMkvM^k vの第一成分に等しい。従って、問題はv=Mkvv = M^kvであるような最小の正整数kkを求めることと言い換えられる。

この問題はbaby-step giant-stepで解ける。B=KB= \lceil \sqrt K \rceilとする。a0,a1,a2,...,aB1a_0, a_1, a_2, ..., a_{B-1}についてmod  K\mod Kでの値をmapのキー、添字をmapの値として保持しておく。(キーが重複する場合、そこでサイクルに入るので、それまでに00が見つかっていなければ打ち切ってよい。) k=iBjk= iB-j, j{0,1,...,B1}j \in \{0, 1, ..., B-1\}とする時、v=Mkvv = M^kvが成り立つためにはMjv=MiHvM^j v = M^{iH}vが成り立つ必要がある。したがって、i=1,2,...,Bi=1, 2, ..., BについてMiBvM^{iB}vを計算してaiBa_{iB}を求め。この値が先に作ったマップに入っていれば対応する添字jjを取り出すとk=iBjk=iB-jが答えの候補になる。ただし、MMは正則とは限らないので、Mjv=MiBvM^j v = M^{iB}vは必要条件でしかない。つまり、aiBjmod  Ka_{iB-j} \mod Kが必ず00になるわけではない。実際にMiBjvM^{iB-j}vを計算して確認する必要がある。

ハッシュテーブルを使った場合の期待計算量はO(K){O}(\sqrt K)

2021年10月3日日曜日

ABC 221 H - Count Multiset

分割数っぽい数え上げなので分割数っぽいDPを考える。

まずは分割数のDPを思い出す。自然数nnkk個の正整数の和に分割する場合の数をP(n,k)P(n, k)とする。分割の中に1を含まないものはnkn-kkk分割のすべての項を11増加させて得られ、分割の中に1を含むものはn1n-1k1k-1分割に1を付加すれば得られるのだった。漸化式で表すと

P(n,k)=P(nk,k)+P(n1,k1) P(n, k) = P(n-k, k) + P(n-1, k-1)

このDPを、同じ数をMM個より多くは含まないという制約(以下、単に制約と呼ぶ)に合うように修正することを考える。制約付きの分割の総数をP(n,k)P'(n, k)とする。

上の遷移の一つ目の項、つまり分割の中に1を含まないものをnkn-kkk分割のすべての項を11増加させて得る場合については、制約はそのまま守られるのでこのままでよさそう。一方、二つ目の項、つまり、分割の中に1を含むものを数えたい場合、このままだと1をM+1M+1個含むものも数えてしまうことになるので、これを除きたい。

nnkk分割で11をちょうどM+1M+1個含み、他は制約を満たしているようなものの総数 = n(M+1)n-(M+1)k(M+1)k-(M+1)分割で1を含まず、かつ制約を満たしているようなものの総数 = n(M+1)(k(M+1))n-(M+1)- (k-(M+1))、つまりnkn-kk(M+1)k-(M+1)分割で、制約を満たしているようなものの総数

と言い換えると、最後の量はP(nk,k(M+1))P'(n-k, k-(M+1))に等しいので、漸化式は

P(n,k)=P(nk,k)+P(n1,k1)P(nk,k(M+1)) P'(n, k) = P'(n-k, k) + P'(n-1, k-1) - P'(n-k, k-(M+1))

となる。


スターリング数っぽい数え上げがスターリング数っぽいDPでできる、はけっこう見るけど、分割数っぽい数え上げではうまくいく問題を見た記憶がなくて、遷移を考え始めるまでに時間がかかった……が、例えばJOI 2009 予選 F - ビンゴ がそうだったのを思い出した。

2021年10月2日土曜日

第八回 アルゴリズム実技検定

満点だった。

L - K番目の絶対値

総和の絶対値がDD以下であるような連続部分列を数える問題が解ければよさそう。累積和Si=A1+...+AiS_i = A_1 + ... + A_i上で言い換えると各iiについてSiSjD|S_i-S_j| \le Dであるようなj<ij < iを数えればよく、これはS0,S1,...,Si1S_0, S_1, ..., S_{i-1}の中で[SiD,Si+D][S_i-D, S_i+D]に含まれるようなものを数えることに等しい。数え上げをO(NlogN){O}(N \log N)で解くと、全体でO(NlogNlogiAi){O}(N \log N \log \sum_i |A_i|)

順序対を数えることにすれば尺取りでできる。確かに。

M - バランス

SoundHound Inc. Programming Contest 2018 Masters Tournament E - + Graph

O - 色分けトーナメント

  • トーナメントは22N12 \cdot 2^N-1頂点の完全二分木とすると、制約(Wi,Li)(W_i, L_i)WiW_iLiL_iのLCAまでWiW_iLiL_iが勝ち上がってWiW_iが勝つこととみなせる。
  • ある選手を青に塗ると決めても赤に塗ると決めても有効な塗り方は同数ある。(どの有効な塗り方についても、すべての色を反転したものが有効な塗り方であるため。)

dpv[x]=\operatorname{dp}_v[x] =頂点vvを根とする部分木に属する左からxx番目の選手の色を決め打った時に、部分木vvに属する選手の塗り方で(部分木vvに含まれる制約を満たし、かつ)vvが勝ち上がるようなものの総数、とする。dpv\operatorname{dp}_vvvの子をc1,c2c_1, c_2としてdpc1,dpc2\operatorname{dp}_{c_1}, \operatorname{dp}_{c_2}から線形で作れるので、下から処理していけばよい。根に関するdp\operatorname{dp}の総和を2倍したものが答えになる。

各深さのdp\operatorname{dp}の長さの総和はちょうど2N2^Nになるので、全体の計算量はO(N2N+M){O}(N 2^N + M)

2021年9月12日日曜日

日本橋ハーフマラソン 2021 増刊号 A - 農場王X

評価関数を作ってビームサーチした。

前提

収穫機を買うのをどこでやめるか問題はしばらく考えずに、収穫機も資金に換算したスコアで物事を考えることにした。

評価関数

収穫機を設置/撤去する場所の持つべき望ましい性質を列挙して、それらの組み合わせで評価関数を作る。評価はマス毎に行い、価値の高いマスに収穫機を設置して価値の低いマスから収穫機を撤去する貪欲法を前提とする。また、理想的には、収穫機のあるマスの価値の総和を取ると盤面の価値になっていてほしい。

以下の評価関数に従って貪欲法をするとして、収穫機を買うのを止めるタイミングを全探索すると2.6億程度のスコアになった。

マスの価値

基本的には設定の通り、マスを覆う連結成分のサイズ×野菜の価値がそのマスの価値と考えるとよさそう。まだ出現していない野菜については時刻が離れると価値が指数的に下がるとして調整した。時刻の値は野菜の出現日と消失日の2種類があるが、消失日に従って下がるとしたほうがよかった。

また、既に出現している野菜についても、やはり消失日が遠いと価値が指数的に下がるとしたほうがスコアがよいようだった。

マスの価値の伝搬

現在か近い未来に価値の高い野菜が生えるマスの周辺は価値が高いと考えられる。ただ、具体的に価値をどう伝搬するかが問題だった。周辺にどれだけ野菜が多かろうと1ターンで覆えるマスは1つだけなので、野菜が多いエリアを過大評価しないようにする必要がある。

いろいろ試した結果、最大連結成分からの最短経路DAGを作って、その逆順に各頂点vvmaxpvの親頂点(pの価値)\max_{pはvの親頂点}(pの価値)に減衰率を掛けたものを加算していくことにした。

  • これだと距離について指数的に価値が減っていくことになるけれど、価値が3倍なら3ターン掛けてでもいくべき、と考えると反比例で減っていくほうが自然に思える。ただ、こちらは高速な表現ができなかった。
  • 最大連結成分から到達する前に消失してしまう野菜の価値は伝搬しないようにする。

連結していることの価値

収穫機の連結性は維持したい。これを収穫機のないマスについて言い換えると、連結成分の隣は価値が大きい。収穫機のあるマスについて言い換えると、連結成分の関節点は非関節点より価値が大きい。

収穫機が数個のうちはいくつかの連結成分に分離して遠くの野菜を取りに行く可能性も考慮するつもりだったが、試してみるとそれで得られる利益がほぼないことがわかったので、最終的にはひとつの連結成分を伸縮することを前提とした方針に変えた。つまり、評価関数に含めるのではなく、収穫機を撤去するマスは非関節点で、収穫機を置くマスは連結成分の隣とした。

また、下記のビームサーチをする際には収穫機のあるマスの価値の総和を盤面の価値としたが、この時は非関節点が多い配置のほうが(次の撤去候補が多いぶん)やや良いという考えに基づいて、非関節点の評価値に1より少し大きい定数を掛けた。

ビームサーチ

上の評価関数を調整すると、局所的には明らかな問題が見つからなくなった。大きな改善があるとしたら「この日は上のほうに収穫機が集まっているけれど、長期的には実は下に集まったほうが得だった」のような状況をできるだけ減らすくらいで、これは適切に状態をまとめてビームサーチすることで実現できそうと思った。

ビームサーチの前提として似た盤面をまとめるために、全体を8×8の4個の領域に区切って、各領域に収穫機が何個あるかで盤面を同一視することにした。ただ、序盤についてはこの同一視はやりすぎで、区切る領域を少し増やしたほうが良いようだった。最終的には時間経過で16個→5個→4個と分割数を減らすように調整した。

終盤のほうが重要なのでビーム幅は終盤に大きいほうがよく、幅30から幅150まで増えていくようにした。

まだ収穫機を買うのをいつ止めるかという問題が残っている。今度は収穫機の調達数で全探索するわけにもいかないので、830日目以降は買わないという単純な仕組みにした。ここは時間があればもう少し詰めたかった。

2021年9月2日木曜日

ARC 126 E - Snack

子供iiが種類jjの菓子をxi,jx_{i, j}個もらうとすると、与えられた問題は以下の条件でxi,j\sum x_{i, j}を最大化する問題と考えられる:

  1. j=1Nxi,jCii[M]\sum_{j=1}^Nx_{i,j} \le C_i \qquad\forall i \in [M]
  2. i=1Mxi,jAjj[N]\sum_{i=1}^Mx_{i, j} \le A_j \qquad \forall j \in [N]
  3. 0xi,jBii[M],j[N]0 \le x_{i, j} \le B_i \qquad \forall i \in [M], \forall j \in [N]
  4. xi,jZi[M],j[N]x_{i, j} \in \mathbb Z \qquad \forall i \in [M], \forall j \in [N]

ただし、[M]={1,2,...,M},[N]={1,2,...,N}[M] = \{1, 2, ..., M\}, [N] = \{1, 2, ..., N\}。実は4の整数制約は外してもよい。つまり、このILPの最適解はLP緩和の最適解にもなっている。以下はConfortiのInteger Programmingのp. 133を基にした説明。


定義: m×nm \times n行列AAの行を2つの集合SSRRに分割する: S˙R=[m]S \dot{\cup} R = [m]SSの行ベクトルの総和 - RRの行ベクトルの総和が0,±10, \pm 1のみからなるベクトルであるとき、S,RS, RAAの公平な行二彩色 (equitable row-bicoloring) と呼ぶ。

定理: 行列AA0,±10, \pm 1のみからなり、各列の非ゼロ成分は高々2個であるとする。AAが公平な行二彩色可能であれば、全ユニモジュラである。

上の制約の1, 2の係数行列について考えると、1の行と2の行に分割すれば公平になっている定理の条件を満たし、全ユニモジュラである。

定理: AAm×nm \times n整数行列とする。AAが全ユニモジュラならば、任意のl,uZn,dZml, u \in \mathbb Z^n, d \in \mathbb Z^mについて凸多面体Q:={x:Axd,lxu}Q := \{x: Ax \le d, l \le x \le u\}は整数多面体である、

この定理より上の制約1~3によって与えられる凸多面体は整数多面体なので、任意の目的関数について(有界なら)最適解の少なくとも一つは整数解である。


従って、ILPに関する双対、つまり元の問題のLP緩和のLP双対に整数制約を課したものを考えると、これについても強双対性が成り立つ。双対問題は以下の条件でi=1MCipi+j=1NAjqj+i=1MBij=1Nri,j\sum_{i=1}^MC_ip_i + \sum_{j=1}^NA_jq_j+\sum_{i=1}^MB_i\sum_{j=1}^Nr_{i, j}を最小化する問題である:

  • pi+qj+ri,j1i[M],j[N]p_i + q_j + r_{i, j} \ge 1 \qquad \forall i \in [M], \forall j \in [N]
  • pi0,qj0,ri,j0i[M],j[N]p_i \ge 0, q_j \ge 0, r_{i, j} \ge 0 \qquad \forall i \in [M], \forall j \in [N]
  • pi,qj,ri,jZi[M],j[N]p_i, q_j, r_{i, j} \in \mathbb Z \qquad \forall i \in [M], \forall j \in [N]

双対問題を、M×NM \times Nのグリッドのいくつかの行と列を選択して覆うようなイメージで解釈した:

  • 行と列の集合S[M],T[N]S \subseteq [M], T \subseteq [N]を任意に選ぶ。言い換えると、pi=1p_i=1とするiiqj=1q_j=1とするjjを選ぶ。
  • iSi \in SについてコストCiC_iを払う。
  • jTj \in TについてコストAjA_jを払う。
  • SSに含まれる行とTTに含まれる列に覆われないすべてのマス(i,j)(i, j)についてコストBiB_iを払う。

最後の「覆われない」の部分の扱いが面倒に見えるので、さらに言い換える:

  • 最初にコストNi=1MBiN\sum_{i=1}^MB_iを払っておく。
  • S[M],T[N]S \subseteq [M], T \subseteq [N]を任意に選ぶ。k=Tk=|T|とする。
  • iSi \in SについてコストCi(Nk)BiC_i-(N-k)B_iを払う。
  • jTj \in TについてコストAji=1MBiA_j-\sum_{i=1}^M B_iを払う。

さて、[N][N]からkk点選ぶと決めたときの最小コストについて考える。S[M],T[N]S \in [M], T \in [N]について(Nk)i=1MBi+iS(Ci(Nk)Bi)+jTAj(N-k)\sum_{i=1}^MB_i + \sum_{i \in S}(C_i-(N-k)B_i)+\sum_{j \in T}A_jが総コストである。TTAjA_jの小さいほうからkk個取ればよく、SSのほうはCi(Nk)Bi<0C_i-(N-k)B_i < 0であるものだけ取ればよい。Ci(Nk)BiC_i-(N-k)B_ikkが減少すると一点で正から負に切り替わる。具体的にはk(NBiCi)/Bik \le \lfloor (NB_i-C_i)/B_i \rfloorで0以下になる。したがって、この閾値を超えたiiについてCiC_iBiB_iの総和を保持することにすればkkごとにO(1){O}(1)で計算できる。(Ai)(A_i)のソートが必要だから全体の計算量はO(NlogN+M){O}(N \log N + M)


LPの整数性について追記した。

2021年8月28日土曜日

日本橋ハーフマラソン 2021

A - 魔法使いXの戦い

308662点。1つのモンスターにつき、だいたい3回くらいパワーアップできる計算で、3回ならひとつずつ最適な組み合わせを貪欲に取っていけそう。素朴にやるとO(N4){O}(N^4)だが、最後は二分探索でよいのでO(N3logN){O}(N^3 \log N)

まだ回数に余裕があるので、末尾に近いモンスターは4回パワーアップしたいが、これは素朴に探索すると間に合わない。qqに選ぶモンスターから近い数値で固まっているものを省いたりして間に合う程度のノード数に減らした。

探索する順番を工夫すれば少し伸びるかもと思っていろいろ試したが伸びず。

B - マッサージチェア2021

210901点。一点のパワーを変更して干渉する点のパワーを減らすだけの山登りをした。すぐに収束してしまうが、簡単に書けそうな他の遷移もないので多点スタートなどで時間を使い切ることにした。一点のパワーを下がるほうに変更するような完全に無駄な遷移も入れてしまっているなど、いろいろ詰めが甘かった。

AtCoder Adのように、1つのノードを大きくして周りのノードを小さくする操作と、1つのノードを小さくして周りを大きくするような操作を組み合わせて再帰的に頑張るともう少しよくなるかもと思ったが、この時間では書ける気がしなかった。

マス(i,j)(i, j)のパワーを表す変数をpi,jp_{i,j}とし、マス(i,j)(i, j)に正のパワーを与えることをバイナリ変数xi,jx_{i, j}で表すと、素朴なMIP定式化は

maximize Ei,jpi,jE_{i, j}p_{i, j}
subject to

  • 0pi,jNxi,j0 \le p_{i, j} \le Nx_{i, j}
  • pi1,j1N(1xi2,j2)i1i2+j1j21p_{i_1, j_1}-N(1-x_{i_2, j_2})\le |i_1-i_2|+|j_1-j_2|-1

という感じか。


解説を見ると全然問題の性質をとらえられていないなと思う。短時間コンテストは自明な方針を手早く実装したあと細部の詰めで同方針の人にちょっと勝つだけでそれなりの順位がとれてしまうことがありそう。

2021年8月25日水曜日

Treapのunionの計算量に関するメモ

https://www.cs.cmu.edu/~scandal/papers/treaps-spaa98.pdfm,n (mn)m, n \ (m \le n)要素のTreapのunionで期待計算量がO(mlog(n/m)){O}(m \log (n/m))であるものが紹介されている。これを使うと次のことができる:

1要素のTreapがNN個与えられたとし、これらのTreapに任意の順番でN1N-1回unionを適用してNN要素のTreapを作るとする。この時、全体の期待計算量はO(NlogN){O}(N \log N)である。

これはマージテクと同じように理解できる:

まず、定数BBが存在してm,n (mn)m, n\ (m \le n)要素のTreapのunionの期待計算量はBmlog(n/m)B m \log (n/m)以下である。

求める計算量をT(N)T(N)とする。C>0C>0が存在してNN未満の整数xxについてはT(x)CxlogxT(x) \le C x \log xが成り立っていると仮定する。このとき、T(N)CNlogNT(N) \le C N\log Nであることを示せばよい。この際、CBC \ge Bとしてよい。

T(N)maxm+n=N(Bmlognm+T(m)+T(n)) T(N) \le \max_{m+n = N} \bigl (Bm \log \frac{n}{m}+ T(m) + T(n) \bigr)

であるから、任意の分割N=m+n (0<mn)N = m+n \ (0 < m \le n)についてBmlog(n/m)+T(m)+T(n)CNlogNBm \log (n/m) + T(m) + T(n) \le C N \log Nが成り立つことを示せばよい。実際、次のように示せる:

Bmlognm+T(m)+T(n) Bmlognm+Cmlogm+Cnlogn C(mlognm+mlogm+nlogn)= C(mlognm+mlogm+nlognmm)= C(mlognm+mlogm+nlognm+nlogm)= C((m+n)lognm+(m+n)logm)= C(Nlognm+Nlogm)= C(NlognNlogm+Nlogm)= CNlogn CNlogN \begin{aligned}& Bm \log \frac{n}{m}+ T(m) + T(n) \\ \le \ & B m \log \frac{n}{m} + Cm\log m + C n \log n \\ \le \ & C \bigl (m\log\frac{n}{m} + m\log m + n \log n \bigr ) \\ = \ & C \bigl (m \log \frac{n}{m} + m\log m + n \log \frac{n}{m}m \bigr ) \\ = \ & C \bigl (m \log \frac{n}{m} + m\log m + n\log \frac{n}{m} + n \log m \bigr ) \\ = \ & C \bigl ((m+n) \log \frac{n}{m} + (m+n)\log m \bigr ) \\ = \ & C \bigl (N\log \frac{n}{m} + N \log m \bigr) \\ = \ & C(N\log n - N\log m+ N \log m) \\ = \ & CN\log n \\ \le \ & CN\log N \\ \end{aligned}

log1=0\log 1 = 0 問題があるのであまり正確でない。)

2021年8月12日木曜日

JAG Summer Camp 2017 Day 1 C - すごろく

まずはBiB_iがすべて00であるような問題を考える。ループがない、つまり同じマスに二回止まることがないので、ゴール以前の各マスに止まる確率を足し合わせたものが求める期待値になっている。

p(i)=p(i) = サイコロを振ってiiが書かれた面が出る確率 dp[x]=\operatorname{dp}[x] =マスxxに止まる確率

とするとき、0-basedで考えると遷移は

dp[x]=0kxdp[xk]p(k)\operatorname{dp}[x] = \sum_{0 \le k \le x}\operatorname{dp}[x-k]p(k)

となって、これはオンラインFFTで解ける形になっている。

BiB_iが必ずしも0でない場合について考える。Bx>0B_x > 0であるようなマスxxについては、オンラインFFT中にdp[x]\operatorname{dp}[x]に加算する時に、代わりにdp[x+Bx]\operatorname{dp}[x+B_x]に加算すればよい。また、Bx<0B_x < 0、つまり休みのマスについては、そのようなマスに止まる確率×Bx\times |B_x|を結果に足せばよさそう……だが、他のマスからBBの影響で進んできた場合は休まないので、dp\operatorname{dp}を構成し終えてからdp[x]×Bx\operatorname{dp}[x] \times |B_x|を後で足すと正しく計算できない。やはりオンラインFFT中にdp[x]\operatorname{dp}[x]に加算する瞬間に結果に足す必要がある。

2021年7月26日月曜日

KUPC 2016 H - 壁壁壁壁壁壁壁

KUPC 2016 H - 壁壁壁壁壁壁壁

位置iiからi+1i+1に補強材を移動する量をxix_iとして制約を書き下す。n=4n=4なら

  • A1x1B1A_1-x_1 \ge B_1
  • A2+x1x2B2A_2 + x_1-x_2 \ge B_2
  • A3+x2x3B3A_3 + x_2-x_3 \ge B_3
  • A4+x3B4A_4+x_3 \ge B_4

という制約の下でx1+x2+x3+x4|x_1|+|x_2|+|x_3|+|x_4|を最小化する問題になっている。

fi(x)f_i(x)x1,...,xi1,xi=xx_1, ..., x_{i-1}, x_i=xまでを決定した際の最小コストとする。slope trick向けに制約を変形すると、

  • x1A1B1x_1 \le A_1-B_1
  • x1x2(A2B2)x_1 \ge x_2-(A_2-B_2)
  • x2x3(A3B3)x_2 \ge x_3-(A_3-B_3)
  • x3B4A4x_3 \ge B_4-A_4

となって、一番上のx1x_1に関する制約を無視するとfif_iの漸化式が得られる:

  • f1(x)=xf_1(x) = |x|
  • f2(x)=mintx(A2B2)f1(t)+xf_2(x) = \min_{t \ge x - (A_2-B_2)}f_1(t) + |x|
  • f3(x)=mintx(A3B3)f2(t)+xf_3(x) = \min_{t \ge x - (A_3-B_3)}f_2(t) + |x|

登場する操作はすべてslope trickで表現できて、答えは凸性により、B4A4B_4-A_4arg minxf3(x)\argmin_xf_3(x)の大きいほうの位置でf3f_3の値を求めると得られる。

制約x1A1B1x_1 \le A_1-B_1については、この範囲を超えると高いコストがかかることにして対処したい。x1x_1A1B1A_1-B_111超過することによる利益が高々CCであるとき、f1(x)=x+Cmax(0,x(A1B1))f_1(x) = |x| + C\max(0, x-(A_1-B_1))とすればよい。CCの具体的な値としては、制約を11だけ破っている状態を解消するために1つの補強材を端から端へ移動するとN1N-1のコストがかかるので、N1N-1でよい。

2021年7月24日土曜日

CodeChef - CCDSAP Exam

CodeChef - CCDSAP Exam

slope trickの練習問題として解いた。

iiの初期位置をaia_iとし、人iiを位置xxに配置した場合の人1,2,...,i1, 2, ..., iに関するコストの総和の最小値をfi(x)f_i(x)とする。

左右の境界を無視するとfi(x)=mintx2fi1(t)+xai=mintxfi1(t2)+xaif_{i}(x) = \min_{t \le x-2}f_{i-1}(t) + |x-a_{i}| = \min_{t \le x}f_{i-1}(t-2)+|x-a_i|と表せる。これだけなら普通のslope trickで解けるが実際には境界を越えられないところが難しい。

境界を越えたら大きなコストがかかるように、xai|x-a_i|の代わりに定数CCを定めてCmax(0,1x)+xai+Cmax(0,xN)C\max(0, 1-x) + |x-a_i| + C\max(0, x-N)を追加することを考えたが、これは優先度付きキューに一つずつ挿入していく方法では難しそう。平衡二分木で多重集合を管理すればいけそう? → 平衡二分木slope trickを作ろうとしたが、最小値の更新が自明にはできない。おそらく任意のxxについてf(x)f(x)の値が取得できる必要があって、実現方法がわからなかった。ただ、min\minがわからなくてもarg min\argminは容易に取得・更新できる。これだけわかれば最適解を貪欲に復元できそう。最適解における人iiの位置をyiy_iとする。yN=arg minxfN(x)y_N=\argmin_x f_{N}(x)は既知であり、yi+1y_{i+1}が既知であるときyiy_i

yi=min(arg minxfi(x),yi+12)y_i = \min(\argmin_x f_{i}(x), y_{i+1}-2)

と決定できる。arg min\argminが複数ある時はどれを取ってもよい。