Bzoj1005 [HNOI2008]明明的烦恼

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4948  Solved: 1926

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

 

Source

 

数学问题 组合数  高精度 树 prufer序列

利用一个prufer序列对应唯一的树结构这一性质,进行花式组合计算

为了回避麻烦的高精度除法,可以分解质因数,用减指数代替直接除,最后再把各质数乘起来。

答案蜜汁长,2000位高精度WA掉了,压了两位就过了。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 using namespace std;
  7 const int mxn=1010;
  8 int read(){
  9     int x=0,f=1;char ch=getchar();
 10     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 11     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 12     return x*f;
 13 }
 14 struct Num{
 15     int x[2001],len;
 16     void read(int a){
 17         len=0;
 18         while(a){x[++len]=a%100;a/=100;}
 19         return;
 20     }
 21     inline int max(int a,int b){return a>b?a:b;}
 22     void operator * (int b){
 23         for(int i=1;i<=len;i++)
 24             x[i]*=b;
 25         for(int i=1;i<=len;i++)
 26             if(x[i]>9){
 27                 x[i+1]+=x[i]/100;
 28                 x[i]%=100;
 29                 len=max(len,i+1);
 30             }
 31         return;
 32     }
 33 }a;
 34 void Print(Num a){
 35     while(!a.x[a.len])a.len--;
 36     for(int i=a.len;i;i--)
 37         if(i==a.len)printf("%d",a.x[i]);
 38         else printf("%02d",a.x[i]);
 39     puts("");
 40     return;
 41 }
 42 int pri[mxn],cnt=0;
 43 bool vis[mxn];
 44 void init(){
 45     for(int i=2;i<mxn;i++){
 46         if(!vis[i])pri[++cnt]=i;
 47         for(int j=1;j<=cnt && pri[j]*i<mxn;j++){
 48             vis[pri[j]*i]=1;
 49             if(i%pri[j]==0)break;
 50         }
 51     }
 52     return;
 53 }
 54 int p[mxn],d[mxn],n,m,smm=0;
 55 void calc(int x,int f){
 56 //    printf("calc:%d %d\n",x,f);
 57     for(int i=1;i<=cnt && pri[i]<=x;i++){
 58         while(x%pri[i]==0){
 59             p[i]+=f;
 60             x/=pri[i];
 61         }
 62     }
 63     return;
 64 }
 65 int main(){
 66 //    freopen("bzoj_100511.in","r",stdin);
 67 //    freopen("bzoj_1005.out","w",stdout);
 68     int i,j;
 69     init();
 70     n=read();
 71     if(n==1){
 72         i=read();
 73         if(!i || i==-1)printf("1\n");
 74         else printf("0\n");
 75         return 0;
 76     }
 77     for(i=1;i<=n;i++){
 78         d[i]=read();
 79         if(!d[i]){
 80             printf("0\n");return 0;
 81         }
 82         if(d[i]!=-1)smm+=d[i]-1;
 83         else m++;
 84     }
 85     if(smm>n-2 || !m){
 86         printf("0\n");return 0;
 87     }
 88     for(i=n-2;i>1;i--)calc(i,1);
 89     calc(m,n-2-smm);
 90     for(i=n-2-smm;i>1;i--)calc(i,-1);
 91     for(i=1;i<=n;i++){
 92         for(j=d[i]-1;j>1;j--){
 93             calc(j,-1);
 94         }
 95     }
 96     a.read(1);
 97     for(i=1;i<=cnt;i++){
 98         for(j=1;j<=p[i];j++)
 99             a.operator *(pri[i]);
100     }
101     Print(a);
102     return 0;
103 }

 

posted @ 2017-04-16 20:05  SilverNebula  阅读(239)  评论(0编辑  收藏  举报
AmazingCounters.com