Count [HNOI2004] Tree: 1211
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3432 Solved: 1295
[Submit][Status][Discuss]
Description
A tree of n nodes, it is assumed that node is v1, v2, respectively, ..., VN, known in the i-th node vi degree of DI, Q satisfying such conditions the number of trees different trees. Given n, d1, d2, ..., dn, satisfies the number of programming required output d (vi) = di tree.
Input
The first line is a positive integer n, the tree has n nodes. The second row has the number n, denotes the i-th degree di, of the i th node, i.e. tree. Where 1 <= n <= 150, to ensure that the input data satisfies the condition of the tree does not exceed 10 ^ 17.
Output
Output to meet the conditions of the tree how many trees.
Sample Input
2 1 2 1
Sample Output
Properties of the Xiandiu Prufer sequence:
1. correspondence with unrooted trees.
2. The degree is $ d_i $ dot will appear $ d_i-1 $ Prufer times in sequence.
3. The number of spanning a complete graph $ $ n-th node is $ n ^ {n-2} $
Explain: prufer sequence length $ n-2 $, $ n-$ per Location possibilities.
4. For a given degree of each point unrooted trees, a total of $ \ frac {(n-2 )!} {\ Prod \ limits _ {i = 1} ^ n {(d_i-1)!}} $ Species Happening.
In fact, one $ d_i-1 $ I $ $ remodelable full array.
This question would then cut off just fine with the above conclusion. Numbers by a combination of direct decomposition of the quality factor, remember to Japanese sentence and $ n == 1 $ without Unicom.
#include<cstdio> #include<iostream> #include<cstring> const int N=155; int d[N],n; int vis[N],pri[N],res[N],tot,sum,ans[N*5],bu[N]; void getprime() { for(int i=2;i<=n;i++) { if(!vis[i])pri[++tot]=i,res[i]=tot; for(int j=1;j<=tot;j++) { if(pri[j]*i>n)break; vis[i*pri[j]]=1;res[i*pri[j]]=j; if(i%pri[j]==0)break; } } } void divi(int x,int val) { while(x!=1)bu[res[x]]+=val,x/=pri[res[x]]; } void mult(int a[],int x) { int k=0; for(int i=1;i<=a[0];i++) { int tmp=a[i]*x+k; a[i]=tmp%10; k=tmp/10; } while(k)a[++a[0]]=k%10,k/=10; } int main() { scanf("%d",&n); if(n==1) { int deg; scanf("%d",°); if(!deg)puts("1"); else puts("0"); return 0; } getprime(); for(int i=1;i<=n;i++) { scanf("%d",&d[i]); if(!d[i]) { puts("0"); return 0; } sum+=d[i]-1; } if(sum!=n-2) { puts("0"); return 0; } for(int i=n-2;i>=2;i--) divi(i,1); for(int i=1;i<=n;i++) { for(int j=d[i]-1;j>=2;j--) divi(j,-1); } ans[0]=ans[1]=1; for(int i=1;i<=tot;i++) while(bu[i]--)mult(ans,pri[i]); for(int i=ans[0];i;i--) printf("%d",ans[i]); return 0; }
1005: [HNOI2008] obviously troubles
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7125 Solved: 2818
[Submit][Status][Discuss]
Description
Since obviously learned tree, the tree on the right strange generated interest ...... given numbered 1 to N points, and the final degree certain points, allowing
the connection between any two points may be how many degrees to meet the requirements of the tree was generated?
Input
The first behavior N (0 <N <= 1000 ),
the next N rows, row i + 1-Di given degree of node i, if the degree is not required, enter -1
Output
An integer representing the number of the tree meet different requirements, no solution outputs 0
Sample Input
1
-1
-1
Sample Output
HINT
Two trees are 1-2-3; 1-3-2
The problem is that some point this question is the degree of uncertainty.
Therefore, we first find the $ sum = \ sum d_i-1 $, then selecting from these the overall length of the $ n-2 $
The number of remaining uncertain for some degree, we set of known power point is $ cnt $
So now $ n-2-sum $ positions may be arbitrarily arranged $ n-cnt $ points
Easy to get a final answer
$C_{n-2}^{sum}*\frac{(n-2)!}{\prod \limits _{i=1}^{cnt} {(d_i-1)!}}*(n-cnt)^{n-2-sum}$
#include<cstdio> #include<iostream> #include<cstring> using namespace std; typedef long long ll; const int N=1005; int d[N],n; int vis[N],pri[N],res[N],tot,sum,cnt,ans[N*5],bu[N]; void getprime() { for(int i=2;i<=n;i++) { if(!vis[i])pri[++tot]=i,res[i]=tot; for(int j=1;j<=tot;j++) { if(pri[j]*i>n)break; vis[i*pri[j]]=1;res[i*pri[j]]=j; if(i%pri[j]==0)break; } } } void divi(int x,int val) { while(x!=1)bu[res[x]]+=val,x/=pri[res[x]]; } void mult(int a[],int x) { int k=0; for(int i=1;i<=a[0];i++) { int tmp=a[i]*x+k; a[i]=tmp%10; k=tmp/10; } while(k)a[++a[0]]=k%10,k/=10; } int main() { scanf("%d",&n); getprime(); for(int i=1;i<=n;i++) { scanf("%d",&d[i]); if(d[i]!=-1)sum+=d[i]-1,cnt++; } for(int i=n-2;i>=2;i--) divi(i,1); for(int i=n-2-sum;i>=2;i--) divi(i,-1); for(int i=1;i<=n;i++) { if(d[i]!=-1) { for(int j=d[i]-1;j>=2;j--) divi(j,-1); } } ans[0]=ans[1]=1; for(int i=1;i<=n-2-sum;i++) mult(ans,n-cnt); for(int i=1;i<=tot;i++) while(bu[i])mult(ans,pri[i]),bu[i]--; for(int i=ans[0];i>=1;i--) printf("%d",ans[i]); return 0; }