zoukankan      html  css  js  c++  java
  • P2624 [HNOI2008]明明的烦恼【prufer序列】

    题意

    给出标号为 (1)(N) 的点,以及某些点最终的度数,如果对度数无要求则为 (-1),允许在任意两点间连线,可产生多少棵度数满足要求的树?

    (0 < N leq 1000)

    分析

    首先,令 (k=sum_{d_i eq -1}{1},sum=sum_{d_i eq -1}{(d_i-1)}),由于每棵树对应的 ( ext{prufer}) 序列的长度为 (n-2),而已知度数要求的编号所占位置数为:(sum)。因此,对于有度数要求的编号的方案数为:

    [C_{n-2}^{sum}·frac{sum!}{prod_{d_i eq -1}{(d_i-1)!}} ]

    对于序列剩下的 (n-2-sum) 个位置,每个位置有 (n-k) 个点可以选择。最终的方案总数为:

    [ans=C_{n-2}^{sum}·frac{sum!}{prod_{d_i eq -1}{(d_i-1)!}}·(n-k)^{n-2-sum} ]

    由于数据比较大,所以使用 ( ext{python}) 会简单。

    代码

    n = int(input())
    d = [0 for i in range(0, n + 5)]
    for i in range(1, n + 1):
        d[i] = int(input())
    
    k = 0
    sum = 0
    prod = 1
    for i in range(1, n + 1):
        if d[i] == 0:
            print(0)
            exit()
    
        if d[i] != -1:
            k += 1
            sum += (d[i] - 1)
    
    if sum > n - 2:
        print(0)
        exit()
    
    f = [0 for i in range(0, n + 3)]
    f[0] = 1
    for i in range(1, n + 1):
        f[i] = f[i - 1] * i
    
    ans = f[n - 2] // f[n - 2 - sum]  # sum写成了k
    for i in range(1, n + 1):
        if d[i] != -1:
            ans //= f[d[i] - 1]
    ans *= pow(n - k, n - 2 - sum)
    print(int(ans))
    
    
  • 相关阅读:
    一些开源工具软件
    被伤过的心还可以爱谁
    C函数检测CPU架构为LittleEndian或BigEndian
    C#打印(接录)
    C#Lambda表达式参考
    C#反射 创建对象,调用方法
    datagridview cell 验证事件
    我多想抱着你哭
    C#获取属性
    STM32的位操作的方法
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13627767.html
Copyright © 2011-2022 走看看