《四重计树法》

  1. 有标号无根

prufer 序列,\(n^{n-2}\)。

  1. 有标号有根

prufer 序列,\(n^{n-1}\)。

  1. 无标号有根

设 \(f[n]\) 为 \(n\) 个节点时的答案,有:

\[f[n]=\sum_{k=1}^n\frac{[\sum_{i=1}^ks_i=n-1]\prod_{i=1}^kf[s_i]}{k!}
\]

人话就是 \(F(x)=x\times Euler(F(x))\)。

考虑求导列出 ODE 然后 \(O(n^2)\)。

\[F(x)=x\exp(\sum_{i=0}\frac{F(x^i)}{i})
\]

求导:

\[F'(x)=Euler(F(x))+x(Euler(F(x))(\sum_{i=1}\frac{F(x^i)}{i}{\rm d}x))
\]
\[F'(x)=Euler(F(x))+x(Euler(F(x))(\sum_{i=1}\frac{ix^{i-1}F'(x^i)}{i}))
\]
\[F'(x)=\frac{F(x)}{x}+F(x)(\sum_{i=1}x^{i-1}F(x^i))
\]
\[xF'(x)=F(x)+xF(x)(\sum_{i=1}x^{i-1}F(x^i))
\]
\[F(x)=x(F'(x)-F(x)(\sum_{i=1}x^{i-1}F(x^i)))
\]
\[F(x)=xF'(x)-F(x)(\sum_{i=1}x^iF(x^i))
\]

同理,只需要维护出 \(F(x)\) 就可以维护出 \(F'(x),\sum_{i=1}x^iF(x^i)\) 和后面那个卷积,复杂度 \(O(n^2)\)。

  1. 无标号无根

考虑把每颗无根树变成 以重心为根的有根树

然后我们只需要做一遍有根的再减去不为重心的即可。

不为重心,那么一定有一个子树的大小大于了 \(\lfloor\frac{n}{2}\rfloor\)。

当 \(n\) 为奇数时,每棵树只有一个重心,减去的方案数为:

\[\sum_{i=\lfloor\frac{n}{2}\rfloor+1}^{n-1}f_i\times f_{n-i}
\]

当 \(n\) 为偶数时,有些树可能有两个重心。因此还需要额外减去有两个重心的树。

有两个重心就说明有一个分界的边,两边都恰好有 \(\frac{n}{2}\) 个节点。从 \(f_{\frac{n}{2}}\) 中选出两个方案即可。也就是 \(\binom{f_{\frac{n}{2}}}{2}\)。

#include<cstdio>
const int M=1005;
inline void swap(int&a,int&b){
int c=a;a=b;b=c;
}
inline int pow(int a,int b,const int&mod){
int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
inline int Solve1(const int&n,const int&mod){
static int f[M],g[M],inv[M];
int ans(0);
f[1]=g[1]=inv[1]=1;
for(int i=2;i<=n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<=n;++i){
for(int k=1;k<=i;++k)f[i]=(f[i]+1ll*f[k]*g[i-k])%mod;
f[i]=1ll*f[i]*inv[i-1]%mod;
for(int k=1;k<=i;++k)if(!(i%k))g[i]=(g[i]+1ll*f[k]*k)%mod;
}
ans=f[n];
for(int i=0;i<=n;++i)f[i]=g[i]=inv[i]=0;
return ans;
}
inline int Solve2(const int&n,const int&mod){
static int f[M],g[M],inv[M];
int ans(0);
f[1]=g[1]=inv[1]=1;
for(int i=2;i<=n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<=n;++i){
for(int k=1;k<=i;++k)f[i]=(f[i]+1ll*f[k]*g[i-k])%mod;
f[i]=1ll*f[i]*inv[i-1]%mod;
for(int k=1;k<=i;++k)if(!(i%k))g[i]=(g[i]+1ll*f[k]*k)%mod;
}
ans=f[n];
for(int i=n/2+1;i<n;++i)ans=(ans-1ll*f[i]*f[n-i])%mod;
if(!(n%2))ans=(ans-1ll*f[n/2]*(f[n/2]-1)/2%mod)%mod;
for(int i=0;i<=n;++i)f[i]=g[i]=inv[i]=0;
return(ans+mod)%mod;
}
signed main(){
int t,n,mod;
while(~scanf("%u%u%u",&t,&n,&mod)){
if(t==1){
printf("%u\n",n==1?1:pow(n%mod,(n-2)%(mod-1),mod));
}
if(t==2){
printf("%u\n",n==1?1:pow(n%mod,(n-1)%(mod-1),mod));
}
if(t==3){
printf("%u\n",Solve1(n,mod));
}
if(t==4){
printf("%u\n",Solve2(n,mod));
}
}
}

最新文章

  1. 模拟搭建Web项目的真实运行环境(七)
  2. 制作stick侧边栏导航效果
  3. HTTP协议的几个概念
  4. poj 2186 tarjan求强连通分量
  5. html部分---表单、iframe、frameset及其他字符的用法(以及name、id、value的作用与区别);
  6. Fragment 总结
  7. 【Web】CDN加速效果浅析
  8. 微信支付 V3版
  9. ajax的来龙去脉
  10. Android 实现ActionBar定制
  11. poj 2184 Cow Exhibition(背包变形)
  12. 分布式发布订阅消息系统Kafka
  13. 编程算法 - 数字数组中只出现一次 代码(C)
  14. 设置文件opendilag、savedilog默认路径和文件类型
  15. [精品书单]word排版设计
  16. undo丢失恢复异常恢复,运维DBA反映Oracle数据库无法启动报错ORA-01157 ORA-01110,分析原因为Oracle数据库坏块导致
  17. blender 操作快捷键
  18. cmake与autoconf+automake
  19. mysql中trim()函数的用法
  20. 利用htmlparser读取html文档的内容

热门文章

  1. js Object.prototype.hasOwnProperty() 与 for in 区别
  2. php常考功能函数
  3. Foundation框架介绍
  4. Java线程--CyclicBarrier使用
  5. JUC并发包学习
  6. docker平时使用异常记录
  7. Puppeteer简介
  8. ssh一段时间无操作后自动断开连接(假死)问题
  9. ASP.NET Core 6框架揭秘实例演示[03]:Dapr初体验
  10. Spring高级特性之四:FactoryBean和BeanFactory