题解 P6598 【烷烃计数】

题目传送门

更好的阅读体验

我的生成函数博客(含有此题,与本题解略有不同)

题意简述

  • \(n\) 个碳原子对应的烷烃的同分异构体数量。
  • \(n \leq 10^5\),答案对 \(998244353\) 取模。
  • Tips:即求所有节点度数不超过 \(4\) 的无标号无根树数量。

题目分析

前置知识:烷基计数

设烷基计数的生成函数为 \(F(x)\)

烷基计数是无标号有根树,需要去重。

还是用无标号无根树计数的处理方法:钦定根为重心,减掉不合法的方案数


总数

总数并不是 \(f_n\),因为根节点允许有四个儿子。

其实只要特别考虑根节点就可以了,设所有节点度数不超过 \(4\) 的无标号无根树的生成函数为 \(P(x)\)

跟烯烃计数一样,使用 Burnside 引理和 Polya 定理(括号里的数字代表每个循环的大小):

  • \((1,1,1,1)\)\(F^4(x)\),共有 \(1\) 种。
  • \((1,1,2)\)\(F^2(x)F(x^2)\),共有 \(6\) 种。
  • \((1,3)\)\(F(x)F(x^3)\),共有 \(8\) 种。
  • \((2,2)\)\(F^2(x^2)\),共有 \(3\) 种。
  • \((4)\)\(F(x^4)\),共有 \(6\) 种。

\[P(x)=x\dfrac{F^4(x)+6F^2(x)F(x^2)+8F(x)F(x^3)+3F^2(x^2)+6F(x^4)}{24} \]


去重

接下来考虑去重,惊喜地发现:

  • 砍掉的那一棵子树的根节点的儿子个数一定不超过 \(3\)
  • 剩下的子树的根节点(就是原树的根节点)的儿子个数也一定不超过 \(3\)(因为已经砍掉一棵了)。

然后直接拿 \(F(x)\) 去重即可。

\[ans=p_n-\sum\limits_{k=\lfloor\frac{n}{2}\rfloor+1}^n f_kf_{n-k}-[2|n]C_{f_{\lfloor\frac{n}{2}\rfloor}}^2 \]

时间复杂度 \(O(nlogn)\)


代码

很丑陋的代码……

int main(){
	NTT::pre();
	cin>>n;
	solve();
	for(long long i=0;i<=n;i++) SS[i]=S2[i*2]=S22[i*2]=S3[i*3]=S4[i*4]=S[i];
	
	NTT::solve(SS,SS,S,n,n);
	NTT::solve(SS,SS,S,n,n);
	NTT::solve(SS,SS,S,n,n);
	
	NTT::solve(S2,S2,S,n,n);
	NTT::solve(S2,S2,S,n,n);
	
	NTT::solve(S22,S22,S22,n,n);
	
	NTT::solve(S3,S3,S,n,n);
	
	anss=(SS[n-1]+S2[n-1]*6%mod+S22[n-1]*3%mod+S3[n-1]*8%mod+S4[n-1]*6%mod)%mod*ksm(24,mod-2)%mod;
	for(long long i=n/2+1;i<n;i++) anss=(anss+mod-S[i]*S[n-i]%mod)%mod; 
	if(n%2==0) anss=(anss+mod-S[n/2]*(S[n/2]-1)/2%mod)%mod;
	cout<<anss;
}

完整代码

posted @ 2021-02-24 12:47  苹果蓝17  阅读(192)  评论(0编辑  收藏  举报