题意
给出标号为 (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))