UVa Problem Solution: 10247 - Complete Tree Labeling


Let f(k, d) denote the number of labelings of the k-ary tree of depth d. Moreover, let n(k, d) denote the number of nodes of the tree. The tree contains k subtrees, each contains n(k, d-1) nodes. There are totally  (n(k, d) - 1)! / (n(k, d-1)!)^k ways to partition the n(k, d) - 1 labels into k different subsets, each have the same size of n(k, d-1), therefore  we can draw this recurrence:
   f(k, d) = (n(k, d) - 1)! / (n(k, d-1)!)^k * f(k, d-1)
with base cases of
   f(k, 0) = 1

Code:
  1. /***************************************************************************
  2.  *   Copyright (C) 2008 by Liu Kaipeng                                     *
  3.  *   LiuKaipeng at gmail dot com                                           *
  4.  ***************************************************************************/
  5. /* @JUDGE_ID 00000 10247 C++ "Complete Tree Labeling" */
  6. #include <algorithm>
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <deque>
  10. #include <fstream>
  11. #include <iostream>
  12. #include <list>
  13. #include <map>
  14. #include <queue>
  15. #include <set>
  16. #include <stack>
  17. #include <string>
  18. #include <vector>
  19. #include "big_unsigned.hpp"
  20. using namespace std;
  21. /*
  22.  * Let f(k, d) denote the number of labelings of the k-ary tree of depth d.
  23.  * Moreover, let n(k, d) denote the number of nodes of the tree. The tree
  24.  * contains k subtrees, each contains n(k, d-1) nodes. There are totally 
  25.  * (n(k, d) - 1)! / (n(k, d-1)!)^k ways to partition the n(k, d) - 1 labels
  26.  * into k different subsets, each have the same size of n(k, d-1), therefore 
  27.  * we can draw this recurrence:
  28.  *   f(k, d) = (n(k, d) - 1)! / (n(k, d-1)!)^k * f(k, d-1)
  29.  * with base cases of
  30.  *   f(k, 0) = 1
  31.  */
  32. big_unsigned numbers[22][22];
  33. void gen_numbers()
  34. {
  35.   unsigned powers[22][22];
  36.   for (int k = 1; k <= 21; ++k) {
  37.     powers[k][0] = 1;
  38.     for (int d = 1; d * k <= 21; ++d)
  39.       powers[k][d] = powers[k][d-1] * k;
  40.   }
  41.   unsigned nodes[22][22];
  42.   unsigned max_fac = 0;
  43.   for (int k = 1; k <= 21; ++k) {
  44.     nodes[k][0] = 1;
  45.     for (int d = 1; d * k <= 21; ++d)
  46.       if ((nodes[k][d] = nodes[k][d-1] + powers[k][d]) > max_fac)
  47.         max_fac = nodes[k][d];
  48.   }
  49.   vector<big_unsigned> facs(max_fac);
  50.   facs[0] = 1;
  51.   for (unsigned i = 1; i < max_fac; ++i)
  52.     facs[i] = facs[i-1] * i;
  53.   for (int k = 1; k <= 21; ++k) {
  54.     numbers[k][0] = 1;
  55.     for (int d = 1; d * k <= 21; ++d) {
  56.       numbers[k][d] = numbers[k][d-1];
  57.       for (int i = 1; i != k; ++i) numbers[k][d] *= numbers[k][d-1];
  58.       numbers[k][d] *= facs[nodes[k][d]-1];
  59.       for (int i = 0; i < k; ++i) numbers[k][d] /= facs[nodes[k][d-1]];
  60.     }
  61.   }
  62. }  
  63.         
  64. int main(int argc, char *argv[])
  65. {
  66. #ifndef ONLINE_JUDGE
  67.   freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
  68.   freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
  69. #endif
  70.   gen_numbers();
  71.   for (int k, d; cin >> k >> d; ) cout << numbers[k][d] << '/n';
  72.   return 0;
  73. }

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值