烷基计数&烷烃计数(n^2算法)
烷基计数问题
求每个节点的儿子不超过三个,且大小为$n$的有根树的数量。$1 \leq N \leq 2000$
设$f[i][j]$为总共$i$个节点,根节点度数为$j$的方案数。
考虑从$1到N-1$枚举一个当前最大的子树大小$sz$和选的个数$k$,把他接在原来的部分方案上。
于是就有
$f[i][j]+=f[i-sz*k][j-k]*H^{k}_{\sum_{m=0}^{3} f[sz][m]}$
其中H为可重复的组合数,即$H^{m}_{n}$代表$n$个选$m$个可重复选的方案数,因为需要考虑子树的同构。
满足
$H^{m}_{n}=C^{m}_{m+n-1}=\frac{(m+n-1)!}{m!(n-1)!}=\frac{1}{m!}\prod_{t=n}^{m+n-1} t$
证明见文末。
倒着枚举点的个数不会算重。
最后答案即是$\sum_{i=0}^{3}f[N][i]$.
ll H(int a,int b){
if(b==0) return 1;
if(b==1) return a;
if(b==2) return (ll)ny(2)*(a+1)%mod*a%mod;
if(b==3) return (ll)ny(6)*(a+1)%mod*(a+2)%mod*a%mod;
}
int MAIN(){
cin>>N;
f[1][0]=1;
for(int sz=1;sz<N;sz++){
for(int i=N;i;i--){
for(int j=1;j<=3&&j<i;j++){
for(int k=1;k*sz+1<=i&&k<=j;k++){
int s=0;
for(int p=0;p<=3;p++) s=((ll)s+f[sz][p])%mod;
f[i][j]=((ll)f[i][j]+f[i-sz*k][j-k]*H(s,k)%mod)%mod;
}
}
}
}
ll ans=0;
for(int i=0;i<=3;i++) ans+=f[N][i];
cout<<ans%mod<<endl;
return 0;
}
烷烃计数问题
求每个节点的度数不超过四,且大小为$n$的无根树的数目。$1 \leq n \leq 2000$
考虑将所有无根树的一个重心作为根(显然重心只有一或二个),形成有根树。
这样做一定会满足每棵子树大小不超过$\frac{n}{2}$。
这时需要修改$f[i][j]$的定义,即总共$i$个节点,根的度数为$j$且满足子树大小小于$\frac {n+1}{2}$的方案数。
计算时sz必须满足$sz < \frac {n+1}{2}$
为什么是$\frac {n+1}{2}$?
分类讨论一下:
当重心只有一个时:此时$f[n]$最大子树大小为$\frac {n-1}{2}$
当重心有两个时:此时$f[\frac {n}{2}]$的所有情况都被计算了。
所以这样是刚好把条件全部满足的。
接下来统计答案:
当重心只有一个时,答案为$\sum_{i=0}^{4} f[n][i]$.
当重心有两个时,此时n一定是偶数,两个重心相邻且子树大小均为$\frac{n}{2}$(重心的基本性质)。
所以答案需要额外加上$H^{2}_{\sum^{3}_{i=0}{f[\frac {n}{2}][i]}}$
ll H(int a,int b){
if(b==0) return 1;
if(b==1) return a;
if(b==2) return (ll)ny(2)*(a+1)%mod*a%mod;
if(b==3) return (ll)ny(6)*(a+1)%mod*(a+2)%mod*a%mod;
if(b==4) return (ll)ny(24)*(a+1)%mod*(a+2)%mod*(a+3)%mod*a%mod;
}
int MAIN(){
cin>>N;
f[1][0]=1;
for(int sz=1;sz<(N+1)/2;sz++){
for(int i=N;i;i--){
for(int j=1;j<=4&&j<i;j++){
for(int k=1;k*sz+1<=i&&k<=j;k++){
int s=0;
for(int p=0;p<=3;p++) s=((ll)s+f[sz][p])%mod;
f[i][j]=((ll)f[i][j]+f[i-sz*k][j-k]*H(s,k)%mod)%mod;
}
}
}
}
ll ans=0;
for(int i=0;i<=4;i++) ans+=f[N][i];
if(N%2==0){
int ret=0;
for(int i=0;i<=3;i++) ret=(ret+f[N>>1][i])%mod;
ans+=H(ret,2);
}
cout<<ans%mod<<endl;
return 0;
}
证明: $H^{m}_{n}=C^{m}_{m+n-1}$
不妨设要在长度为$n$的排列中可重复地选择$m$项,成为数列{$x$}。
不妨设{$x$}满足$x_{i-1} \leq x_i$
令$T_i = x_i+i-1$
则有$T_{i-1}<T_i$且$T_i \in [1,n+m-1]$
所以相当于在$[1,n+m-1]$中选择不重复的$m$项构成$T_i$.
于是即证$H^{m}_{n}=C^{m}_{m+n-1}$.