Luogu4492
思路
事实 \(1\):\(n\) 个结点的二叉树剩余分支有 \(n+1\) 个。
这个事实使用数学归纳法不难得证。
事实 \(2\):按如此方案生成的二叉树有 \(n!\) 种,且每种左右子树大小分配方案各 \((n-1)!\) 种。
前一句是可以用事实 \(1\) 立刻得到的,考虑后一句是什么意思。
即,记左子树大小为 \(l\),则有方案数为 \(\binom{n-1}{l}l!(n-l-1)!\),也就是 \((n-1)!\)。
这个柿子 \(\binom{n-1}{l}l!(n-l-1)!\) 枚举哪些点分入左子树,再枚举左右子树形态既得。
记对所有这样的树,其到根距离之和为 \(f_n\),点间距离之和为 \(g_n\)。
规定 \(f_0=g_0=0\)。
分别直接枚举左子树大小即得递推方程。
\[\\
f_n=\sum_{i=0}^{n-1}\binom{n-1}{i}(f_i(n-i-1)!+f_{n-i-1}i!+i!(n-i-1)!i+i!(n-i-1)!(n-i-1))
\\=n!(n-1)+(2\sum_{i=0}^{n-1}\binom{n-1}{i}(n-i-1)!f_i)
\\\]
对 \(g\),我们在根节点统计 LCA 为当前结点的方案数。
\[\\
g_n=f_n+\sum_{i=0}^{n-1}\binom{n-1}{i}(g_i(n-i-1)!+g_{n-i-1}i!+(f_i+i!i)(n-i-1)!(n-i-1)+(f_{n-i-1}+(n-i-1)!(n-i-1))i!i)
\\=f_n+2\sum_{i=0}^{n-1}\binom{n-1}{i}g_i(n-i-1)!+2\sum_{i=0}^{n-1}\binom{n-1}{i}f_i(n-i-1)!(n-i-1)+2(n-1)!\sum_{i=0}^{n-1}i(n-i-1)
\\\]
手算前几项:
\[f:\left<0,0,2,16,\cdots\right>
\]
\[g:\left<0,0,2,24,\cdots\right>
\]
符合样例。
这样就足够 \(O(n^2)\) 了。
注意组合数要 \(O(n^2)\) 递推预处理。
Code
modint C[2005][2005],A[2005];
modint F[2005],G[2005];
int main()
{
uint n;ullt p;scanf("%u%llu",&n,&p);
AnyMod::ChgMod(p);
C[0][0]=1;
for(uint i=1;i<=n;i++)
{
C[i][0]=1;for(uint j=1;j<=i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];
}
A[0]=1;for(uint i=1;i<=n;i++)A[i]=A[i-1]*i;
for(uint i=1;i<=n;i++)
{
for(uint j=0;j<i;j++)F[i]+=C[i-1][j]*F[j]*A[i-j-1];
F[i]*=2;
F[i]+=A[i]*(i-1);
}
for(uint i=1;i<=n;i++)
{
for(uint j=0;j<i;j++)G[i]+=C[i-1][j]*G[j]*A[i-j-1];
for(uint j=0;j<i;j++)G[i]+=C[i-1][j]*F[j]*A[i-j-1]*(i-j-1);
for(uint j=0;j<i;j++)G[i]+=A[i-1]*j*(i-j-1);
G[i]*=2;
G[i]+=F[i];
}
G[n].println();
return 0;
}
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-p4492.html