legend_noa's blog

LFYZ蒟蒻竟然写题解!!!……

导航

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

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

将问题一般化:

  求 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)\left\{ \begin{matrix}s+l-1\\l \end{matrix}  \right\}$


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

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

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

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

  $ s=∑^{m−1}_{k=0}f(size,k)$,

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

$f(i,j)←f(i,j)+f(i−size×k,j−k)\left\{ \begin{matrix}s+k-1\\k \end{matrix}  \right\}$


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

烷烃 (无根树)

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

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

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

$\sum^m_{k=0}f(n,k)+[n\pmod{2}=0]  \left\{ \begin{matrix}\sum^{m−1}_{k=0}f(\frac{n}{2},k)+1\\2 \end{matrix}  \right\} $


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

代码附上

 

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/posts/calculate-the-number-of-structural-isomers-for-alkanes/

posted on 2018-08-06 21:20  legend_noa  阅读(2759)  评论(0编辑  收藏  举报