zoukankan      html  css  js  c++  java
  • [BZOJ-1005&洛谷P2624][HNOI2008]明明的烦恼-【Purfer序列】py+java

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1005
    洛谷:https://www.luogu.com.cn/problem/P2624
    Time Limit: 1 Sec  Memory Limit: 162 MB
    洛谷:时间限制1.00s 内存限制125.00MB

    Description

      自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在
    任意两点间连线,可产生多少棵度数满足要求的树?

    Input

      第一行为N(0 < N < = 1000),
    接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1

    Output

      一个整数,表示不同的满足要求的树的个数,无解输出0

    Sample Input

    3
    1
    -1
    -1

    Sample Output

    2

    HINT

      两棵树分别为1-2-3;1-3-2


    相较于04年的裸的Purfer序列,这题就不是那么裸了。

    假设有k个是已知的度,那么根据Purfer序列的性质我们可以得到这k个已知度的答案:

    令$sum=sum_{d_{i} eq -1}^{ }(d_{i}-1)$

     那么该部分的答案应该为:$frac{sum!}{prod_{d_{i} eq -1}^{ }(d_{i}-1)!}$

     但由于purfer中有n-2个元素,那么这sum个元素的放置方法也有C(n-2,sum)种,即该部分的最终答案为:

    $frac{sum!}{prod_{d_{i} eq -1}^{ }(d_{i}-1)!} imes C_{n-2}^{sum}$

     然后就是剩下的了,剩下的有n-k个顶点,序列空余n-2-sum个位置,那么每个顶点有n-2-sum中放法,即有$(n-k)^{n-2-sum}$种答案。

    那么最终答案也就出来了:

    $frac{sum!}{prod_{d_{i} eq -1}^{ }(d_{i}-1)!} imes C_{n-2}^{sum} imes (n-k)^{n-2-sum}$

     emmmm,还是py一波+JAVA一波吧。。

    以下是AC代码:(Python)

    n=int(input())
    a=[]
    for i in range(n):
        a.append(int(input()))
    sum=0;k=0
    for i in range(n):
        if a[i]!=-1:
            sum+=a[i]-1
            k+=1
        elif a[i]==0:
            print(0)
            exit()
    
    c=1
    for i in range(n-2-sum+1,n-2+1):
        c*=i
    for i in range(2,sum+1):
        c//=i
    
    tot=1
    f=[1]
    for i in range(1,sum+1):
        tot*=i
        f.append(f[i-1]*i)
    for i in range(n):
        if a[i]!=-1:
            tot//=f[a[i]-1]
    
    last=1;
    for i in range(n-2-sum):
        last*=(n-k)
    
    print(c*tot*last)

    (Java代码):

    import java.math.BigInteger;
    import java.util.Scanner;
    
    class Main {
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            int n=sc.nextInt();
            int a[]=new int[1005];
            int mark=0,sum=0,k=0;
            for (int i=1; i<=n; i++){
                a[i]=sc.nextInt();
                if (a[i]==0) mark=1;
                if (a[i]!=-1) {
                    sum+=a[i]-1;k++;
                }
            }
            if (mark==1) {
                System.out.println("0");
                System.exit(0);
            }
            BigInteger s=new BigInteger("1");
            BigInteger num[]=new BigInteger[1005];
            num[0]=new BigInteger("0");
            int mx=n;
            if (sum>n) mx=sum;
            for (int i=1; i<=mx; i++)
                num[i]=num[i-1].add(new BigInteger("1"));
            for (int i=n-2; i>=n-2-sum+1; i--)
                s=s.multiply(num[i]);
            for (int i=2; i<=sum; i++)
                s=s.divide(num[i]);
            BigInteger tot=new BigInteger("1");
            for (int i=1; i<=sum; i++)
                tot=tot.multiply(num[i]);
            BigInteger f[]=new BigInteger[1050];
            f[0]=new BigInteger("1");
            for (int i=1; i<=n; i++)
                f[i]=f[i-1].multiply(num[i]);
            BigInteger cnt=new BigInteger("1");
            for (int i=1; i<=n; i++)
                if (a[i]!=-1)  cnt=cnt.multiply(f[a[i]-1]);
            BigInteger last=new BigInteger("0");
            for (int i=1; i<=n-k; i++) last=last.add(new BigInteger("1"));
            BigInteger tot_last=new BigInteger("1");
            for (int i=1; i<=n-2-sum; i++) tot_last=tot_last.multiply(last);
            System.out.println(s.multiply(tot.divide(cnt)).multiply(tot_last));
        }
    }
    路漫漫兮
  • 相关阅读:
    进程通信之信号通信
    分数化小数
    台湾大学公开课《概率》第五周一道不会作的作业题 ,一种看不懂的解法
    网络子系统53_ip协议分片重组_内存阈值
    Centos 6.3 Realtek Audio Driver Compile
    I.MX6 PHY fixup 调用流程 hacking
    I.MX6 AR8031 寄存器操作
    I.MX6 ethtool 移植
    I.MX6 U-Boot ping网络
    Android tcpdump 使用
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/12189938.html
Copyright © 2011-2022 走看看