烷基计数 题解

好怪的化学题……

题意:n个碳原子组成的烷烃同分异构体个数。或者,形式化的(如果您还没学到有机),求n个点,每个点度数4,且根节点度数3的无标号有根树计数。(其实就是每个点最多三个儿子的树计数)

loj上这个有三版,普通版(n400),加强版(n5000),加强版加强版(n100000)

首先说一下:n个元素选m次的方案数是Cn+m1m。考虑有哪些元素可以重复选。

  1. 普通版O(n3)

我们设dp[i]是有i个碳原子的烷烃个数,然后显然最多有三个儿子,那就枚举一下总点数和两个子树的点数,暴力显然是O(n3)的。

那么我们前面那个组合数有什么用呢?我们发现这三棵子树的点数可能是相等的,但是由于是无标号计数,当两个是相同情况的时候如果直接乘会重复计算。于是我们就需要前面那个组合数来统计答案。

inline int C(int n,int m){
	if(m==1)return n;
	if(m==2)return 1ll*(n+1)*n/2;
	if(m==3){
		return n*n+n*(n-1)*(n-2)*inv6;//inv6是6的逆元 
	}
	return 0;//看不懂就把组合数拆开 还有这题有点卡常少取点模 
}
for(int i=1;i<=n;i++){
	for(int j=0;j<=i;j++){
		for(int k=j;j+k<=i;k++){
			int l=i-(j+k);
			if(l<k)continue;//防止计重 
			if(j==k&&k==l)dp[i]+=C(dp[j],3);//均省略取模以增加可读性 
			else if(j==k)dp[i]+=C(dp[j],2)*dp[l];
			else if(k==l)dp[i]+=C(dp[k],2)*dp[j];
			else dp[i]+=dp[j]*dp[k]*dp[l];
		}
	}
}
  1. 加强版O(n2)

首先显然我们之前枚举了太多我们用不到的选项和重复选项。而且重复这块很致命。考虑改变状态设计。

dp[k][i][j]i个碳原子有j个子树的时候的方案数。那么我们可以分别枚举当前子树大小i,母树(就是子树的父亲为根的树)大小j,子树数量k和与当前子树大小相同的子树个数l,这样我们就可以以一个稍微大一点点的常数和少一个n的复杂度逐步转移状态,同时少了很多重复。(dp能优化的大概到此为止了)。同时我们倒序枚举j,这样第一维可以压掉。

int main(){
	scanf("%d",&n);
	dp[1][0]=1;
	for(int i=1;i<n;i++){//子树大小 显然不能到n 
		for(int j=n;j>i;j--){//父亲大小 显然最小不能到i 
			for(int k=1;k<=3;k++){//有几棵子树 
				for(int l=1;l<=k&&l*i<j;l++){//有几棵和i长的一样的子树 
					dp[j][k]=dp[j][k]+1ll*C(dp[i][0]+dp[i][1]+dp[i][2],l)*dp[j-i*l][k-l];
				}
			}
		}
	}
	printf("%d",dp[n][4]);
}
  1. 加强版加强版O(nlogn)

Polya定理。先咕着。不知道什么时候能补。也许AFO了都补不上。

首先既然要Polya定理那就先找置换。发现因为有3个子树所以有A33=6个置换,就是3的全排列。(置换不懂的先去oiwiki看看群论,然后这里的置换就是三棵子树之间互相置换,这里是从(1,2,3)置换到下面的)。这里枚举出来:

首先设答案的生成函数为F(x),我们要求第nan就是答案。那么:

对于置换(1,2,3),三个自环,互不影响,直接三次方卷上。

对于置换(1,3,2),(2,1,3),(3,2,1),两个环,一个一元一个二元。所以是3F(x)F(x2)

剩下的置换是三元环,也就是2F(x3)

于是按照polya定理的柿子写出来搞个生成函数形式,就变成了这个诡异的方程:

F(x)=1+xF(x)3+3F(x)F(x2)+2F(x3)6

我管你会不会解反正我不会解

好了以上是三个月前naive的我(虽然现在也一样naive)的吐槽。我们其实可以把上边那个 22 东西牛顿迭代求,对着 F(x) 求个偏导就行了。代码不想写了,有点工业。

posted @   gtm1514  阅读(93)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示