zoukankan      html  css  js  c++  java
  • 【bzoj1005】[HNOI2008]明明的烦恼

    1005: [HNOI2008]明明的烦恼

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 4175  Solved: 1660
    [Submit][Status][Discuss]

    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

    该题运用到了树的prufer编码的性质:
      (1)树的prufer编码的实现
            不断 删除树中度数为1的最小序号的点,并输出与其相连的节点的序号  直至树中只有两个节点
      (2)通过观察我们可以发现
            任意一棵n节点的树都可唯一的用长度为n-2的prufer编码表示
            度数为m的节点的序号在prufer编码中出现的次数为m-1
      (3)怎样将prufer编码还原为一棵树??
            从prufer编码的最前端开始扫描节点,设该节点序号为 u ,寻找不在prufer编码的最小序号且没有被标记的节点 v ,连接   u,v,并标记v,将u从prufer编码中删除。扫描下一节点。
    该题需要将树转化为prufer编码:
     n为树的节点数,d[ ]为各节点的度数,m为无限制度数的节点数。
    则            
    所以要求在n-2大小的数组中插入tot各序号,共有种插法;
    在tot各序号排列中,插第一个节点的方法有种插法;
                               插第二个节点的方法有种插法;
                                          ………
    另外还有m各节点无度数限制,所以它们可任意排列在剩余的n-2-tot的空间中,排列方法总数为
     
    根据乘法原理:
     
     
    然后就要高精度了…..但高精度除法太麻烦了,显而易见的排列组合一定是整数,所以可以进行质因数分解,再做一下相加减。
    关于n!质因数分解有两种方法,第一种暴力分解,这里着重讲第二种。
      若p为质数,则n!可分解为 一个数*,其中  <n
    所以 

    ——转自怡红公子

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<ctime>
     7 #include<algorithm>
     8 using namespace std;
     9 #define mod 1000000
    10 int n,m,tot,cnt,len=1,d[1010],pri[1010],num[1010],f[1010],ans[1010];
    11 inline int read()
    12 {
    13     int x=0,f=1;  char ch=getchar();
    14     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
    15     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
    16     return x*f;
    17 }
    18 void gets()//线性筛素数
    19 {
    20     memset(f,1,sizeof(f));
    21     for(int i=2;i<=1000;i++)
    22     {
    23         if(f[i])  pri[++cnt]=i;
    24         for(int j=1;j<=cnt;j++)
    25         {
    26             if(pri[j]*i>1000)break;
    27             f[pri[j]*i]=0;
    28             if(i%pri[j]==0)break;
    29         }
    30     }
    31 }
    32 void solve(int x,int f)//暴力分解x
    33 {
    34     for(int i=1;i<=x;i++)
    35     {
    36         int k=i;
    37         for(int j=1;j<=cnt;j++)
    38         {
    39             if(k<=1)  break;
    40             while(k%pri[j]==0)
    41             {num[j]+=f;  k/=pri[j];}
    42         }
    43     }
    44 }
    45 void mul(int x)//100万进制高精乘
    46 {
    47     for(int i=1;i<=len;i++)  ans[i]*=x;
    48     for(int i=1;i<=len;i++)  
    49     {
    50         ans[i+1]+=ans[i]/mod;
    51         ans[i]%=mod;
    52     }
    53     while(ans[len+1])  
    54     {len++;  ans[len+1]=ans[len]/mod;  ans[len]%=mod;}
    55 }
    56 void print()//输出高精度数
    57 {
    58     for(int i=len;i;i--)
    59         if(i==len)  printf("%d",ans[i]);
    60         else printf("%06d",ans[i]);
    61 }
    62 int main()
    63 {
    64     n=read();  ans[1]=1;
    65     gets();//读素数表
    66     if(n==1)  //特判
    67     {
    68         int x=read();  
    69         if(!x)  printf("1
    ");
    70         else printf("0
    ");
    71         return 0;
    72     }
    73     for(int i=1;i<=n;i++)  
    74     {    
    75         d[i]=read();
    76         if(!d[i])  {printf("0
    "); return 0;}
    77         if(d[i]==-1)  m++;
    78         else d[i]--,tot+=d[i];
    79     }
    80     if(tot>n-2)  {printf("0
    "); return 0;}
    81     solve(n-2,1);
    82     solve(n-2-tot,-1);
    83     for(int i=1;i<=n;i++)
    84         if(d[i])  solve(d[i],-1);
    85     for(int i=1;i<=cnt;i++)
    86         while(num[i]--)
    87             mul(pri[i]);
    88     for(int i=1;i<=n-2-tot;i++)
    89         mul(m);
    90     print();
    91     return 0;
    92 }
  • 相关阅读:
    方法的重载
    this用法
    简单的随机数 代码和笔记
    java内存简单剖析
    day 28
    day 27
    day 26
    day 25
    day 24
    day 23
  • 原文地址:https://www.cnblogs.com/chty/p/5852259.html
Copyright © 2011-2022 走看看