• bzoj1211 [HNOI2004]树的计数


    Description

    一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵。给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数。

    Input

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

    Output

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

    Sample Input

    4
    2 1 2 1

    Sample Output

    2

    正解:$prufer$序列。
    有一个结论,如果一个点的度数为$d$,那么它在$prufer$序列中出现$d-1$次。

    知道这个以后我们就可以直接算了,$Ans=frac{n-2!}{prod_{(d-1)!}}$

    注意两个细节,一是要分解质因数,二是要特判无解情况。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 
     6 using namespace std;
     7 
     8 int f[160][160],ans[160],d[160],vis[160],prime[160],n,cnt,sum;
     9 ll Ans;
    10 
    11 il int gi(){
    12   RG int x=0,q=1; RG char ch=getchar();
    13   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    14   if (ch=='-') q=-1,ch=getchar();
    15   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    16   return q*x;
    17 }
    18 
    19 il ll qpow(RG ll a,RG ll b){
    20   RG ll ans=1;
    21   while (b){
    22     if (b&1) ans*=a; a*=a,b>>=1;
    23   }
    24   return ans;
    25 }
    26 
    27 il void sieve(){
    28   for (RG int i=2;i<=n;++i){
    29     if (!vis[i]) prime[++cnt]=i;
    30     for (RG int j=1,k;j<=cnt;++j){
    31       k=i*prime[j]; if (k>n) break;
    32       vis[k]=1; if (i%prime[j]==0) break;
    33     }
    34   }
    35   return;
    36 }
    37 
    38 il void factor(RG int n){
    39   RG int x=n;
    40   for (RG int i=1;i<=cnt;++i){
    41     if (x%prime[i]) continue;
    42     while (x%prime[i]==0) x/=prime[i],++f[n][i];
    43   }
    44   return;
    45 }
    46 
    47 il void add(int *a,RG int x,RG int v){
    48   for (RG int i=1;i<=cnt;++i) a[i]+=v*f[x][i]; return;
    49 }
    50 
    51 int main(){
    52 #ifndef ONLINE_JUDGE
    53   freopen("count.in","r",stdin);
    54   freopen("count.out","w",stdout);
    55 #endif
    56   n=gi(),sieve(),Ans=1;
    57   for (RG int i=1;i<=n;++i){
    58     d[i]=gi()-1; if (d[i]<0 && n!=1) puts("0"),exit(0); sum+=d[i];
    59   }
    60   if (sum!=n-2) puts("0"),exit(0);
    61   for (RG int i=2;i<=n;++i) factor(i);
    62   for (RG int i=2;i<=n-2;++i) add(ans,i,1);
    63   for (RG int i=1;i<=n;++i)
    64     for (RG int j=2;j<=d[i];++j) add(ans,j,-1);
    65   for (RG int i=1;i<=cnt;++i) Ans*=qpow(prime[i],ans[i]);
    66   cout<<Ans; return 0;
    67 }
  • 相关阅读:
    HDU 6187 Destroy Walls
    HDU1596 find the safest road
    美国机遇号失联已久,NASA想出一奇招,网友看后:这我上我也行!
    萨拉飞机或掉入恐怖深渊,那里满是核废料
    Problem : 恢复一棵树
    Problem : [tju1071]一个简单题
    Problem : 马农
    人类首个“触日”探测器绕日第二圈
    美国三岁男孩森林迷路两天 遇黑熊“热心帮忙”终获救
    世上最孤独鸭子去世
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7605660.html
Copyright © 2020-2023  润新知