【BZOJ 1005】 1005: [HNOI2008]明明的烦恼 (prufer数列+高精度)
1005: [HNOI2008]明明的烦恼
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4981 Solved: 1941Description
自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在
任意两点间连线,可产生多少棵度数满足要求的树?Input
第一行为N(0 < N < = 1000),
接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1Output
一个整数,表示不同的满足要求的树的个数,无解输出0
Sample Input
3
1
-1
-1Sample Output
2HINT
两棵树分别为1-2-3;1-3-2
Source
【分析】
先特判无解的情况。
假设$sum=\sum(d[i]-1)|[d[i]!=-1]$
$ss=\sum 1 [d[i]!=-1]$
则$Ans=C_{n-2}^{sum}*\dfrac{sum!}{\Pi(d[i]-1)!}*(n-ss)^{n-2-sum}$
即$Ans=\dfrac{(n-2)!}{(n-2-sum)!*\Pi(d[i]-1)!}*(n-ss)^{n-2-sum}$
这些数值都不会超过n的,先手动消因子,然后Ans用高精度,就是高精乘单精。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 1010 8 #define mod 10000 9 10 int cnt[Maxn],d[Maxn]; 11 12 struct hugeint 13 { 14 int w[Maxn],l; 15 hugeint() {memset(w,0,sizeof(w));l=0;} 16 friend hugeint operator * (hugeint x,int y) 17 { 18 for(int i=0;i<=x.l;i++) x.w[i]*=y; 19 for(int i=0;i<=x.l;i++) x.w[i+1]+=x.w[i]/mod,x.w[i]%=mod; 20 while(x.w[x.l+1]!=0) x.w[x.l+2]+=x.w[x.l+1]/mod,x.w[++x.l]%=mod; 21 while(x.w[x.l]==0&&x.l>0) x.l--; 22 return x; 23 } 24 }; 25 26 void cal(int x,int y) 27 { 28 for(int i=2;i<=x*x;i++) if(x%i==0) 29 { 30 while(x%i==0) cnt[i]+=y,x/=i; 31 } 32 if(x!=1) cnt[x]+=y; 33 } 34 35 int main() 36 { 37 int n; 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++) scanf("%d",&d[i]); 40 if(n==1&&d[1]>0) printf("0\n"); 41 else 42 { 43 int sum=0,ss=0; 44 for(int i=1;i<=n;i++) if(d[i]!=-1) sum+=d[i]-1,ss++; 45 else if(d[i]==0||d[i]>=n) {printf("0\n");return 0;} 46 if(sum>n-2) printf("0\n"); 47 else 48 { 49 // for(int i=1;i<=n;i++) if(d[i]!=-1) d[i]--; 50 for(int i=1;i<=n;i++) cnt[i]=0; 51 for(int i=2;i<=n-2;i++) cal(i,1); 52 for(int i=2;i<=n-2-sum;i++) cal(i,-1); 53 for(int i=1;i<=n;i++) if(d[i]!=-1) 54 { 55 for(int j=2;j<=d[i]-1;j++) cal(j,-1); 56 } 57 cal(n-ss,n-2-sum); 58 hugeint ans;ans.w[0]=1; 59 for(int i=2;i<=n;i++) while(cnt[i]--) ans=ans*i; 60 printf("%d",ans.w[ans.l]); 61 for(int i=ans.l-1;i>=0;i--) printf("%04d",ans.w[i]);printf("\n"); 62 } 63 } 64 return 0; 65 }
2017-04-25 15:36:48