洛谷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))



全部评论

相关推荐

Aki-Tomoya:窝趣,人家这是先富带动后富,共同富裕了属于是
投递英伟达等公司10个岗位
点赞 评论 收藏
分享
给🐭🐭个面试机会吧:嘿,mvbatis
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务