??给定树上一些节点的度数,对其他节点的度数不做要求,求可能的树的数量。
??考虑求树所对应的 Prufer 序列的数量。Prufer 序列是一种能够完全表示标号无根树的信息的序列,它的构造及还原方式这里略去,只强调它的两个性质:
根据 Prufer 序列的构造与还原方法,含 \(n\;(n\ge 2)\) 个点的标号无根树 \(T\) 与长度为 \(n-2\),\(p_i \in [1,n]\) 的序列 \(\{p_{n-2}\}\) 一一对应。
令 \(T\) 中标号为 \(i\) 的结点度数为 \(d_i\),则 \(i\) 在 \(T\) 对应的 Prufer 序列中出现 \(d_i-1\) 次。
因此,题意相当于给定一些元素在长度为 \(n-2\) 的序列中出现的次数,求可能的序列总数。为每个被限定的数在还没被选中的位置中选择一些位置,最后在空位上随意填上没有被限制的数,用这个思路就可以求出答案。
Java 在高精度运算方面还是一如既往的方便。
代码
import java.util.*;
import java.math.*;
public class Main{
public static BigInteger bigint(int n){
return new BigInteger(String.valueOf(n));
}
public static BigInteger C(int n,int m){
BigInteger ans=bigint(1);
int i;
for (i=0;i<m;i++)
ans=ans.multiply(bigint(n-i)).divide(bigint(i+1));
return ans;
}
public static BigInteger pow(int a,int b){
BigInteger ans=bigint(1);
BigInteger mul=bigint(a);
while (b>0){
if ((b&1)>0) ans=ans.multiply(mul);
mul=mul.multiply(mul); b>>=1;
}
return ans;
}
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int i,n,m,k,cnt;
BigInteger ans=bigint(1);
n=in.nextInt(); m=n-2; cnt=0;
if (n==1){
k=in.nextInt();
if (k!=0&&k!=-1) System.out.println("0");
else System.out.println("1");
return;
}
for (i=0;i<n;i++){
k=in.nextInt();
if (k==-1){
cnt+=1; continue;
}
ans=ans.multiply(C(m,k-1));
m-=k-1;
}
ans=ans.multiply(pow(cnt,m));
System.out.println(ans);
in.close();
}
}
原文:https://www.cnblogs.com/Kilo-5723/p/12004166.html