码迷,mamicode.com
首页 > 其他好文 > 详细

计算烷烃的同分异构体个数 (结构异构)

时间:2018-08-06 21:41:57      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:com   技巧   nbsp   限制   一个   ret   方便   cal   int   

本质上就是一个无标号无根树带度数限制的计数问题.

将问题一般化:

求 n 个点的无标号无根树的个数, 且每个点的度数不超过 m.

烷基 (有根树)

首先考虑计算烷基的个数 (即有根树).

考虑暴力 DP. 设状态为 $f(i,j,k)$, 表示当前共有 $i$个点, 最大的子树大小为 $j$, 且根的度数为 $k$. 对于状态 $f(i,j,k)$, 通过枚举最大子树的个数 l 和次大子树的大小 size, 有$f(i,j,k)=∑l∑s+f(i?jl,size,k?l)(s+l?1l)$


其中 $s=∑ja=1∑m?1b=0f(j,a,b)$, 组合数是用来可重集计数的.

这是$ O(n^3m^2) $的. 显然可以前缀和优化, 但是空间撑不住. 还可以做得更好.

考虑如何省掉 $j$ 这一维状态. 即设状态为 $f(i,j)$, 表示当前共有 $i$ 个点, 根的度数为 $k$.

考虑 DP 的一个技巧: 强行规定转移顺序. 即, 先 $1\cdotsn$ 枚举 size, 表示强制用最大子树大小为 size 的情形来转移. 不妨设

  $ s=∑m?1k=0f(size,k)$,

那么对于一个 $f(i,j)$, 再枚举一个最大子树 (即子树大小为 size 的子树) 的个数 k, 我们便有转移

$f(i,j)←f(i,j)+f(i?size×k,j?k)(s+k?1k)$


这是 $O(n^2m2)$ 的. 如果是算烷基的话, 便是 $O(n^2)$ 的.

烷烃 (无根树)

本来我想枚举主链长度来做的, 后来发现直接利用树的重心来做非常方便.

首先只要某个点 $u$ 满足其子树大小都 $≤n2$, 那么这个点是这颗树的重心. 比较显然的是, 重心最多只会有两个, 并且有两个重心的情形, 两个重心一定相邻, 并且另一个重心做根的时候, 这个重心的子树大小为 $n2$. (当然 $n$ 必须要是偶数)

然后很多无根树同构的问题就可以通过重心转化为有根树同构. 烷烃就可以这么计数. 因为我们可以在 DP 烷基的时候, 强制$ size<n2 $(注意是小于), 这样求出的 $f(i,j)$ 就是点数为 $i$ 且重心度数为 $j$ 的无根树个数. 那么答案为$m∑k=0f(n,k)+[nmod2=0](∑m?1k=0f(n2,k)+12)$


前一项为一个重心的情形, 后一项为两个重心的情形.

代码附上

 

def C(n, k):
    ret = 1
    for i in range(k):
    ret *= n - i
    for i in range(1, k + 1):
    ret //= i
    return ret

def calc(n, m):
    dp = [[0 for i in range(m + 1)] for i in range(n + 1)]
    dp[1][0] = 1
    for size in range(1, (n - 1) // 2 + 1):
    s = sum(dp[size][:-1])
    for i in range(n, size, -1):
        for j in range(1, m + 1):
        for k in range(1, j + 1):
            if size * k < i:
            dp[i][j] += dp[i - size * k][j - k] * C(s + k - 1, k)
    ret = sum(dp[n])
    if n % 2 == 0:
    ret += C(sum(dp[n // 2][:-1]) + 1, 2)
    return ret

n = int(input())
print(calc(n, 4))

 

出处:
计算烷烃的同分异构体个数(结构异构) 【J.O】_Debug

链接:http://debug18.com

计算烷烃的同分异构体个数 (结构异构)

标签:com   技巧   nbsp   限制   一个   ret   方便   cal   int   

原文地址:https://www.cnblogs.com/fseject-2002/p/9432902.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!