Successfully reported this slideshow.
順列原案、問題文:宮村 解答:宮村 解説:宮村
問題概要   以下の条件を満たす長さ N の数列 X の個数を数    える。   1. 任意の i に対して X[j]=i なる j が存在する。   2. X[s] = t   3. X[a[i]] < X[b[i]] (1≦i≦C...
問題読み替え   条件 1 は単に順列であることを言っているだけ。   簡単のため以下のように問題を読み替える。   2. X[s] = N-t+1   3. X[a[i]] > X[b[i]] (1≦i≦C)    ( ただし i ≠...
グラフとして解釈する   各番号を頂点とし、番号 b[i] から a[i] へ辺を張った    頂点数 N のグラフを考える。   このとき、この有向グラフで頂点 s が N-t+1 番目に    くるトポロジカル順序の個数を求めれば良い。...
グラフとして解釈する   入次数 1 以下という制限があるので、有向閉路を    持たない場合は根付き木が複数個集まったような    グラフになる。                 s
グラフとして解釈する   連結成分毎に分けて考えてもいいが、ダミーノード    を根としてつけると簡単になる。   この場合、頂点 s が N-t+2 番目にくるようなトポロ    ジカル順序の個数を求めれば良い。             ...
ここまでのまとめ   結局、有向閉路を持たない場合は以下のような問    題に帰着できる。   ノード数 N の根付き木が与えられる。このとき、ノー    ド v が k 番目にくるようなトポロジカル順序の個数    を求めよ。    (N...
解法   動的計画法で解く。   根から v までのパス上で計算する。   以下の解説では番号を 0-indexed にする。
根からのパス            このパス上で DP する   rootroot       v                            v
状態の関係式   S[u]={u を根とする部分木のサイズ } とする。   S[u] = 1 + Σ S[c]     ただし、 c は u の全ての子
状態の関係式   T[u] = {u を根とする部分木のトポロジカル順序の    総数 } とする。   T[u] = (Π T[c]) * (S[u]-1)! / (Π S[c]!)      ただし、 c は u の全ての子   階乗...
状態をどのようにとるか   根から v へのパス上のノードを浅い順に V[0]=root,    V[1], …, V[depth]=v, V[d+1]=dummy とする。   S[dummy] = 0, T[dummy] = 1 として...
状態の関係式                                                  オーバーフローに注意   DP[i][j] = (Σ_{0≦k<j} DP[i-1][k])    * combination(N...
計算量   状態数が depth * N でおよそ N^2 通りある。   ひとつの関係式を真面目に計算したら O(N) 程度    かかって全体で O(N^3) となり TLE しそう。
計算量   (Π T[c]) * (S[i]-S[i+1]-1)! / (Π S[c]!) の部分は j に    依存しないので最初に計算しておけばよい。   Σ_{0≦k<j} DP[i-1][k] は DP[i-1][j] を j の...
解答例   宮村    C++ : 139 行 2517 byte    Java: 171 行 3327 byte
Upcoming SlideShare
Loading in …5
×

Permutation

653 views

Published on

  • Be the first to comment

  • Be the first to like this

Permutation

  1. 1. 順列原案、問題文:宮村 解答:宮村 解説:宮村
  2. 2. 問題概要 以下の条件を満たす長さ N の数列 X の個数を数 える。 1. 任意の i に対して X[j]=i なる j が存在する。 2. X[s] = t 3. X[a[i]] < X[b[i]] (1≦i≦C) ( ただし i ≠ j ならば a[i] ≠ a[j]) 2 ≦ N ≦ 2000 0≦C≦N
  3. 3. 問題読み替え 条件 1 は単に順列であることを言っているだけ。 簡単のため以下のように問題を読み替える。 2. X[s] = N-t+1 3. X[a[i]] > X[b[i]] (1≦i≦C) ( ただし i ≠ j ならば a[i] ≠ a[j] ) もとの条件を満たす数列を X[i] := N – X[i] + 1 で 置き換えた数列の数を数えているに過ぎない
  4. 4. グラフとして解釈する 各番号を頂点とし、番号 b[i] から a[i] へ辺を張った 頂点数 N のグラフを考える。 このとき、この有向グラフで頂点 s が N-t+1 番目に くるトポロジカル順序の個数を求めれば良い。 もちろん、 DAG でなければトポロジカル順序が定 義できないので、閉路があれば即座に 0 を返す。 有向閉路の判定は O(N+C) なり O(N*C) なりで簡 単にできる。
  5. 5. グラフとして解釈する 入次数 1 以下という制限があるので、有向閉路を 持たない場合は根付き木が複数個集まったような グラフになる。 s
  6. 6. グラフとして解釈する 連結成分毎に分けて考えてもいいが、ダミーノード を根としてつけると簡単になる。 この場合、頂点 s が N-t+2 番目にくるようなトポロ ジカル順序の個数を求めれば良い。 root s
  7. 7. ここまでのまとめ 結局、有向閉路を持たない場合は以下のような問 題に帰着できる。 ノード数 N の根付き木が与えられる。このとき、ノー ド v が k 番目にくるようなトポロジカル順序の個数 を求めよ。 (N は元の問題とは異なることに注意 )
  8. 8. 解法 動的計画法で解く。 根から v までのパス上で計算する。 以下の解説では番号を 0-indexed にする。
  9. 9. 根からのパス このパス上で DP する rootroot v v
  10. 10. 状態の関係式 S[u]={u を根とする部分木のサイズ } とする。 S[u] = 1 + Σ S[c] ただし、 c は u の全ての子
  11. 11. 状態の関係式 T[u] = {u を根とする部分木のトポロジカル順序の 総数 } とする。 T[u] = (Π T[c]) * (S[u]-1)! / (Π S[c]!) ただし、 c は u の全ての子 階乗を使わずに二項係数を使って計算しても良い。
  12. 12. 状態をどのようにとるか 根から v へのパス上のノードを浅い順に V[0]=root, V[1], …, V[depth]=v, V[d+1]=dummy とする。 S[dummy] = 0, T[dummy] = 1 としておくと楽。 G[i] = {V[i] を根とする部分木 }, G[d+1]= 空とする。 DP[i][j] = {G-G[i+1] で、 V[i] が j 番目に来るような トポロジカル順序の総数 } とすると、最終的に DP[depth][k] が答となる。
  13. 13. 状態の関係式 オーバーフローに注意 DP[i][j] = (Σ_{0≦k<j} DP[i-1][k]) * combination(N-S[V[i+1]]-1-j, S[V[i]]-S[V[i+1]] - 1) * (Π T[c]) * (S[i]-S[i+1]-1)! / (Π S[c]!) ただし、 c は V[i] の V[i+1] 以外の子 0 j-1 j j+1 N-S[V[i+1]]-1 V[i] V[i-1] はこのどこかにある 全部で N-S[V[i+1]] 個 この中から S[V[i]]-S[V[i+1]]-1 個選ぶ
  14. 14. 計算量 状態数が depth * N でおよそ N^2 通りある。 ひとつの関係式を真面目に計算したら O(N) 程度 かかって全体で O(N^3) となり TLE しそう。
  15. 15. 計算量 (Π T[c]) * (S[i]-S[i+1]-1)! / (Π S[c]!) の部分は j に 依存しないので最初に計算しておけばよい。 Σ_{0≦k<j} DP[i-1][k] は DP[i-1][j] を j の小さい方 から加算していけば同じ計算を繰り返さずに済む。 ( 和が出てくる DP を高速化する典型手法 ) または、累積和を計算しておいて O(1) で表引きで きるようにしておく、と考えてもよい。 こうすると、計算量は全体で O(N^2) となる。
  16. 16. 解答例 宮村 C++ : 139 行 2517 byte Java: 171 行 3327 byte

×