• [HNOI2004]树的计数


    题目描述

    输入输出格式

    输入格式:

    输入文件第一行是一个正整数n,表示树有n个结点。第二行有n个数,第i个数表示di,即树的第i个结点的度数。其中1<=n<=150,输入数据保证满足条件的树不超过10^17个。

    输出格式:

    输出满足条件的树有多少棵。

    输入输出样输入样例#1:

    4                     
    2 1 2 1
    
    输出样例#1:
    2

    Prüfer编码与Cayley公式

    给出几个链接:

    http://www.matrix67.com/blog/archives/682

    http://blog.csdn.net/justesss/article/details/38129101

    http://blog.csdn.net/yuyanggo/article/details/49951597

    总的来说,就是说:

    1.n个节点的生成树有n^(n-2)

    2.对于n个点,度为di

    方案数=(n-2)!/(∏(di-1)!)

    对于这题直接套第2个公式

    分解质因子再化简

    注意判断树能否构成

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int d[1001],n,vis[1001],prime[1001],pre[1001],tot,sum;
     7 long long s[1001],ans;
     8 long long qpow(long long x,int y)
     9 {
    10     long long res=1;
    11     while (y)
    12     {
    13         if (y&1) res=res*x;
    14         x=x*x;
    15         y=y/2;
    16     }
    17     return res;
    18 }
    19 int main()
    20 {
    21     int i,j;
    22     cin>>n;
    23     for (i=1; i<=n; i++)
    24     {
    25         scanf("%d",&d[i]);
    26         if (d[i]==0&&1!=n)
    27         {
    28             cout<<0;
    29             return 0;
    30         }
    31         sum+=d[i]-1;
    32         for (j=2; j<=d[i]-1; j++)
    33             s[j]--;
    34     }
    35     if (sum!=n-2)
    36     {
    37         cout<<0;
    38         return 0;
    39     }
    40     for (i=2; i<=n-2; i++)
    41         s[i]++;
    42     for (i=2; i<=n; i++)
    43     {
    44         if (vis[i]==0)
    45         {
    46             pre[i]=i;
    47             tot++;
    48             prime[tot]=i;
    49         }
    50         for (j=1; j<=tot; j++)
    51         {
    52             if (prime[j]*i>n) break;
    53             vis[i*prime[j]]=1;
    54             pre[i*prime[j]]=prime[j];
    55             if (i%prime[j]==0) break;
    56         }
    57     }
    58     ans=1;
    59     for (i=n; i>=2; i--)
    60         if (pre[i]!=i)
    61         {
    62             s[pre[i]]+=s[i];
    63             s[i/pre[i]]+=s[i];
    64             s[i]=0;
    65         }
    66     for (i=n; i>=2; i--)
    67     {
    68         if (s[i]<0)
    69         {
    70             cout<<0;
    71             return 0;
    72         }
    73         ans*=qpow(i,s[i]);
    74     }
    75     cout<<ans;
    76 }
  • 相关阅读:
    家庭记账本开发进度6
    家庭记账本开发进度5
    家庭记账本开发进度4
    家庭记账本开发笔记3
    大道至简阅读笔记01
    个人作业 数组(续)
    二维数组
    个人作业1-数组
    软件工程第一周开课微博
    第一周学习进度条报告
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7635966.html
Copyright © 2020-2023  润新知