题解 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;
}