题目大意:
告诉你树上每个节点的度数,让你构建出这样一棵树,问能够构建出树的种树
这里注意数量为0的情况,就是
当 n=1时,节点度数>0
n>1时,所有节点度数相加-n!=n-2 可以通过通过除了根,必然有n-1个节点作为上一个节点的儿子来理解
然后通过学习prufer序列可知
每一颗树都能够建成唯一的序列,这里的n-2个数就是任意插入到prufer序列中,这很明显就是一个排列,那么之后就是计算
ans = (n-2)!/(w[1]!*w[2]!..w[n]!) w[i]表示i节点上的度数减1,或者理解为以最大的点n作为根,i有多少个儿子节点。
这里不取模,防止值溢出,要分解质因数
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <vector> 5 using namespace std; 6 #define pii pair<int,int> 7 int n , w[200] , num[200]; 8 vector<pii> v[200]; 9 10 void solve(int m) 11 { 12 if(m==1) return; 13 int tmp = m; 14 for(int i=2 ; i<=m ; i++){ 15 if(m%i==0){ 16 int cnt = 0; 17 while(m%i==0){ 18 m/=i; 19 cnt++; 20 } 21 v[tmp].push_back(make_pair(i , cnt)); 22 } 23 } 24 if(m>1) v[tmp].push_back(make_pair(m , 1)); 25 // for(int i=0 ; i<v[tmp].size() ; i++) cout<<v[tmp][i].first<<" "<<v[tmp][i].second<<endl; 26 } 27 void init() 28 { 29 for(int i=1 ; i<=150 ; i++) solve(i); 30 } 31 void update(int k , int flag) 32 { 33 for(int i=0 ; i<v[k].size() ; i++){ 34 pii u=v[k][i]; 35 num[u.first]+=u.second*flag; 36 } 37 } 38 void mul(long long &ans , int k , int tim) 39 { 40 for(int i=1 ; i<=tim ; i++) ans=ans*k; 41 } 42 int main() 43 { 44 // freopen("Sweet.in" , "r" , stdin); 45 init(); 46 while(~scanf("%d" , &n)){ 47 memset(num , 0 , sizeof(num)); 48 int sum=0 , flag=true; 49 for(int i=1 ; i<=n ; i++){ 50 scanf("%d" , &w[i]); 51 if(n!=1 && w[i]<1) flag=false; 52 if(n==1 && w[i]!=0) flag=false; 53 w[i]--; 54 sum+=w[i]; 55 for(int j=1 ; j<=w[i] ; j++) update(j , -1); 56 } 57 if((n>1&&sum!=n-2) || flag==false){ 58 cout<<0<<endl; 59 continue; 60 } 61 for(int i=1 ; i<=n-2 ; i++) update(i , 1); 62 long long ans = 1; 63 for(int i=1 ; i<=n-2 ; i++){ 64 if(num[i]) mul(ans , i , num[i]); 65 } 66 cout<<ans<<endl; 67 } 68 return 0; 69 }
我还在坚持,我还未达到我所想,梦~~一直在