洛谷P2624 [HNOI2008]明明的烦恼(Prufer序列+组合数学)

洛谷P2624 [HNOI2008]明明的烦恼(Prufer序列+组合数学)

**题目:**给你n个节点的树中某些节点的度数,其他节点的度数任意,问有多少种满足题意的树。

思路:

​ 假设给出n个节点的K个节点度数确定,且分别为 d 1 , d 2 , d 3 . . . d k ​ d_1,d_2,d_3...d_k​ d1,d2,d3...dk。我们令 a i = d i − 1 a_i=d_i-1 ai=di1, 且设 s u m = ∑ i = 1 k a i ​ sum= \sum _{i=1} ^{k}a_i​ sum=i=1kai

那么有 a n s = C ( a 1 n − 2 ) ∗ C ( a 2 n − 2 − a 1 ) ∗ . . . C ( a k n − 2 − a 1 − a 2 . . − a k − 1 ) = ( n − 2 ) ! ( n − 2 − s u m ) ! ∗ Π i = 1 k a i ! ∗ ( n − k ) ( n − 2 − s u m ) ans=C {a_1 \choose n-2}*C {a_2 \choose n-2-a_1}*...C {a_k \choose n-2-a_1-a_2..-a_{k-1}}=\frac{(n-2)!}{(n-2-sum)!*\Pi_{i=1} ^{k}a_i!}*(n-k)^{(n-2-sum)} ans=C(n2a1)C(n2a1a2)...C(n2a1a2..ak1ak)=(n2sum)!Πi=1kai!(n2)!(nk)(n2sum)

代码:

def quick_pow(a,b):
    ans=1
    while b>0:
        if (b&1)>0 :
            ans*=a
        a*=a
        b>>=1
    return ans
def init(n):
    fac = [0 for i in range(n + 1)]
    fac[0]=1
    for i in range(1,n+1):
        fac[i]=fac[i-1]*i
    return fac
if __name__ == '__main__':
    # a,b=[int(i) for i in (input().split())]
    # print(a,b)
    # print(quick_pow(a,b))
    n=int(input())
    du=[]
    for i in range(n):
        x=int(input())
        du.append(x)
    if n==1:
        if du[0]>0:
            print(0)
        else:
            print(1)
        exit()
    sum=0
    for i in du:
        if i==0:
            print(0)
            exit()
        if i==-1:
            continue
        sum+=i-1
    if sum>n-2:
        print(0)
        exit()
    #此时n>=2且du[]>1,且sum<=n-2
    fac=init(n)
    ans=fac[n-2]//fac[n-2-sum]
    k=0
    for i in du:
        if i==-1:
            continue
        ans//=fac[i-1]
        k+=1
    ans*=quick_pow(n-k,n-2-sum)
    print(int(ans))



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值