把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【洛谷2624】[HNOI2008] 明明的烦恼(Python+利用prufer序列结论求解)

点此看题面

大致题意: 给你某些点的度数,其余点度数任意,让你求有多少种符合条件的无根树。

\(prufer\)序列

一道弱化版的题目:【洛谷2290】[HNOI2004] 树的计数

这同样也是一道利用\(prufer\)序列求解的题。

还是考虑到由\(prufer\)序列得到的结论:对于给定度数为\(d_{1\sim n}\)的一棵无根树共有\(\frac{(n-2)!}{\prod_{i=1}^n(d_i-1)!}\)种情况

但这次就不能直接套公式了。

推式子

考虑对于已知度数的点,设其个数为\(k\),且\(d_i-1\)的和为\(s\)

然后对于这些已知的点,我们易得方案数为:

\[\frac{s!}{\prod_{i=1}^k(d_i-1)!} \]

由于这\(k\)个点可以任选,因此还需乘上一个组合数,得到:

\[C_{n-2}^k\cdot\frac{s!}{\prod_{i=1}^k(d_i-1)!} \]

则剩下的\(n-2-s\)个位置是可以任意排列的,而又共有\(n-k\)个点,因此总方案数为:

\[C_{n-2}^s\cdot\frac{s!}{\prod_{i=1}^k(d_i-1)!}*(n-k)^{n-2-s} \]

然后就可以直接算了。

求解答案

\(Python\)大法好,无需高精度除法,也无需质因数分解\(23333\)

代码

n=(int)(input());k=0;s=0;a=[0 for i in range (n+5)];#初始化
for i in range(1,n+1):
    a[i]=(int)(input());
    if a[i]==0:print(0);exit();#判断无解
    if a[i]!=-1:k+=1;s+=a[i]-1;#统计k与s
if s>n-2:print(0);exit();#判断无解
f=[0 for i in range(n+5)];f[0]=1;#建立阶乘数组
for i in range(1,n+1):f[i]=f[i-1]*i;#预处理阶乘
ans=ans=(f[n-2]//f[s]//f[n-2-s])*f[s];#初始化ans为C(n-2,s)*s!
for i in range(1,n+1):
    if a[i]!=-1:ans//=f[a[i]-1];#计算答案
print(ans*pow(n-k,n-2-s));#计算答案

posted @ 2019-03-24 23:39  TheLostWeak  阅读(626)  评论(1编辑  收藏  举报