Bzoj1005 [HNOI2008]明明的烦恼
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
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 }
本文为博主原创文章,转载请注明出处。