作問:kuronosu1024
元の問題文
整数 N が与えられます。
N 個の頂点からなる互いに異なる(ラベルなし、根なし)木の総数を X とします。 X を998244353 で割った余りを求めてください。
想定エスパー法
N に対して解の大きさが指数関数的に増加していることより、組み合わせ論的な数と予想できます。
また、N<4 での値がかなり小さいことより対称性が強いものに焦点を当てると、後は気合で木の個数であることをエスパーします。
解説
分割数DPの要領で解くことができます。(FPSを使えば N 倍高速ですが、ここでは解説しません)
1) 根付き木の数を数える
まず、N 頂点の根付き木の総数について考えます
根に部分木を追加していくことを考えると、dp[i] を i 頂点の根付き木の総数と定義して愚直的な遷移を次のように考えられます
・ A∈Pi について、( Pi は自然数 i の分割の全体集合) B[j] を A に含まれる j の個数として、
dp[i+1]=A∈Pi∑j∏dp[j]HB[j]=A∈Pi∑j∏(B[j]dp[j]+B[j]−1)
これで遷移はできるにはできますが、とりうる A の種類数( =∣Pi∣ )は非常に大きな数になるので工夫する必要があります。
(分割とは 例)
例えば i=5 において、頂点数 5 の根付き木の作り方は次の 5 通りに分けられます
- 根に、大きさがそれぞれ {1,1,1,1}である計4つの木をつなげる
- 根に、大きさがそれぞれ {2,1,1}である計3つの木をつなげる
- 以下同様に、 {2,2},{3,1},{4}
この {1,1,1,1} や {3,1} といった集合を 4 の分割といいます
(例終わり)
dp1[i][j] を、i 頂点の根付き木の総数であって、根につながる部分木の大きさが全て j 頂点以下であるものの総数と定義します。(dp[i]=dp1[i][i−1])
A のうち最も大きい数 k を含まれる B[k] 個全て削除したものを A′ とし、それに対応する B を B′ として分けて考えると
j∏(B[j]dp[j]+B[j]−1)=j∏(B′[j]dp[j]+B′[j]−1)⋅(B[k]dp[k]+B[k]−1)
k , B[k] が等しいもの同士をまとめると、(この時、Pi′=(Piのうちすべての要素がk−1以下であるもの) とすると A′∈Pi−kB[k]′ が成り立つので)まとめた総和は
A′∈Pi−kB[k]′∑j∏(B′[j]dp[j]+B′[j]−1)⋅(B[k]dp[k]+B[k]−1)=dp1[i−kB[k]+1][k−1]⋅(B[k]dp[k]+B[k]−1)
さらに、同じ k についてもまとめて
x=1∑⌊i/k⌋dp1[i−kx+1][k−1]⋅(xdp[k]+x−1)
この総和は dp1[i+1][k]−dp1[i+1][k−1] に等しく、dp[i+1] を求めるには、取りうる k,B[k] について上式を求めればよく、その取りうる k,B[k] というのは O(NlogN) 種類で済みます。
また、2項係数も隣同士であるため dp1[i−kx+1][k−1]⋅(xdp[k]+x−1) も適切に実装すればそれぞれ O(1) で計算できます。
よって、 O(N2logN) で dp[N] を求めることができ、今回の制約でこれは十分高速です。
2) 根なし木の数を数える
根なし木は根となる頂点を区別しないため、求めた値から重複分を減らす必要があります。重複分を数えるために木の重心を考えます。(根と重心が一致するもののみ数えることで重複なく根なし木の数を数えることができます。)
N が奇数の時
このとき木の重心は常に 1 個 です。木の重心につながる部分木の大きさは常に N/2 以下であるので、dp1[N][(N−1)/2] がそのまま答えになります。
N が偶数の時
このとき木の重心は常に 1 個か 2 個で、1 個の時は N が奇数の時と同様に求められます (ただし、 N/2 の部分木があると重心が2個になってしまうので、代わりに N/2−1 とする必要があります)。
2 個の時は、その間の辺で分割したときちょうど N/2 頂点の二つの木に分けられるので、そのような木は (2dp[N/2]+1) だけ存在します。
以上より、適切な前計算で必要なDPテーブルを O(N2logN) で求めることができるため、この問題にACすることができます。