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)