首先n个点的这样生成的二叉树有n!种。
因此这就不再是一个期望问题,而是计数问题!
可能没逆元,烦躁qaq
考虑给每个点按生成顺序标号,我们来计算i->fa[i]这条边对答案的贡献。
我们枚举i的子树大小j,那么这条边就会被经过j*(n-j)次。
再考虑i子树内部形态数和外部形态数。
i子树内部形态数显然是
j!∗Cj−1n−i
j
!
∗
C
n
−
i
j
−
1
。(标号一定要大于i)
然后考虑把i子树看做一个点,1~i的点的二叉树形态有i!种。
然后把剩余的n-j-i+1个点挂到这棵树上,由于不能再向i子树内插点,所以形态数为
∏k=1n−j−i+1(i+k−2)
∏
k
=
1
n
−
j
−
i
+
1
(
i
+
k
−
2
)
把这些都乘起来,化简一下,就得到了我们的答案:
没有除法哦!不过要 O(n2) O ( n 2 )
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 2010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,mod,C[N][N],fac[N],ans=0;
inline void inc(int &x,int y){x+=y;x%=mod;}
int main(){
// freopen("a.in","r",stdin);
n=read();mod=read();fac[0]=1;
for(int i=1;i<=n;++i) fac[i]=(ll)fac[i-1]*i%mod;
for(int i=0;i<=n;++i) C[i][0]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
for(int i=1;i<=n;++i)
for(int j=1;j<=n-i+1;++j)
inc(ans,(ll)fac[j]*fac[n-j]%mod*C[n-i][j-1]%mod*(i*(i-1))%mod*j%mod);
printf("%d\n",ans);
return 0;
}