• bzoj1211: prufer序列 | [HNOI2004]树的计数


     题目大意:

    告诉你树上每个节点的度数,让你构建出这样一棵树,问能够构建出树的种树

    这里注意数量为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 }
  • 相关阅读:
    C#代码也VB
    Flash/Flex学习笔记(9):ActionScript3.0与Javascript的相互调用
    原来Silverlight 4中是可以玩UDP的!
    Flash/Flex学习笔记(20):贝塞尔曲线
    Flash/Flex学习笔记(16):如何做自定义Loading加载其它swf
    AS3:让人叹为观止的Flash作品
    Flash/Flex学习笔记(10):FMS 3.5之Hello World!
    Flash/Flex学习笔记(12):FMS 3.5之如何做视频实时直播
    Flash/Flex学习笔记(28):动态文本的滚动控制
    Flash/Flex学习笔记(18):画线及三角函数的基本使用
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4895506.html
Copyright © 2020-2023  润新知