自從明明學了樹的結構,就對奇怪的樹產生了興趣......給出標號爲1到N的點,以及某些點最終的度數,容許在
任意兩點間連線,可產生多少棵度數知足要求的樹?ios
1005: [HNOI2008]明明的煩惱
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4981 Solved: 1941Description
自從明明學了樹的結構,就對奇怪的樹產生了興趣......給出標號爲1到N的點,以及某些點最終的度數,容許在
任意兩點間連線,可產生多少棵度數知足要求的樹?iosInput
第一行爲N(0 < N < = 1000),
接下來N行,第i+1行給出第i個節點的度數Di,若是對度數不要求,則輸入-1ideOutput
一個整數,表示不一樣的知足要求的樹的個數,無解輸出0spa
Sample Input
3
1
-1
-1Sample Output
2HINT
兩棵樹分別爲1-2-3;1-3-2code
Source
【分析】blog
先特判無解的狀況。ip
假設$sum=\sum(d[i]-1)|[d[i]!=-1]$string
$ss=\sum 1 [d[i]!=-1]$it
則$Ans=C_{n-2}^{sum}*\dfrac{sum!}{\Pi(d[i]-1)!}*(n-ss)^{n-2-sum}$io
即$Ans=\dfrac{(n-2)!}{(n-2-sum)!*\Pi(d[i]-1)!}*(n-ss)^{n-2-sum}$event
這些數值都不會超過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