// Complete tree labeling (full tree label) // PC/Ultraviolet IDs: 110605/10247, popularity: C, success rate: average level: 2 // verdict: accepted // submission date: 2011-06-06 // UV Run Time: 0.172 S // copyright (c) 2011, Qiu. Metaphysis # Yeah dot net /// how do I obtain a recursive relationship? T (K, d) indicates the number of K-tree labels with the branch factor K and depth D. Also, // n (K, d) indicates the number of nodes contained in the complete K-Cross Tree with the branch factor K and depth D. According to the definition of a complete K-Cross Tree, // A Full k-Cross Tree with a depth of D contains k Full k-cross numbers with a depth of (d-1, the number of nodes can be expressed as N (K, d-1), K * n (K, d-1) + 1 = N (K, D ). The number of labels for each subtree is // T (K, d-1), then the problem is transformed into the following problem: n (K, d)-1 node, numbered 1-(N (K, d)-1), // is divided into k subsets, each of which has n (K, d-1) nodes, how many partitioning methods are there? Because t (K, d-1) is known as long as the number of Division // method is determined, as long as the subset obtained by each division method is one-to-one matched with each subtree, the elements of each // subset can form a one-to-one ing with the labels in T (K, d-1). If the total number of division methods is X, the relationship is as follows: /// T (K, d) = x * (T (K, d-1) ^ K) (1) //// the number of groups X of the set is equivalent to N (K, d-1) nodes from N (K, d-1) each time, K times in total // The total number of different methods obtained. Set a = (N (K, d)-1), B = N (K, d-1), a = K * B, which has: /// x = C (a, B) * C (a-B, B )*...... * C (A-T * B, B), 0 <= T <= k-1 (2) // you can set (2) according to the number of combinations) formula: // X = (!) /(B !) ^ K) (3) // the final result is: // T (K, d) = (n (K, d)-1 )! /(N (K, d-1 )!) ^ K) * t (K, d-1) // ^ K (4) // It is easy to know that T (K, 0) = 1, n (K, d) = (k ^ (D + 1)-1)/(k-1 ). Then you can further simplify // to: // T (K, d) = (N (K, d)-1 )! /N (K, d-1) ^ K/N (K, D-2) ^ (K ^ 2 )/... /// N (k, 1) ^ (K ^ (d-1) (5) /// we can see that multiplication and division operations involving large numbers are involved. # Include <iostream> # include <vector> # include <iomanip> # include <algorithm> using namespace STD; Class INTEGER {friend ostream & operator <(ostream &, const integer &); Public: INTEGER () {}; // converts an unsigned integer to a large integer. INTEGER (unsigned int A) {if (a = 0) digits. push_back (0); else {While (a) {digits. push_back (a % base); A/= base ;}}};~ INTEGER () {}; integer operator * (const integer &); integer & operator * = (unsigned INT); integer & operator * = (const integer &); integer operator/(integer &); bool is_zero (void) {return digits. empty () ;}; PRIVATE: void zero_justify (void); bool less_equal (integer &, unsigned Int &, integer &); vector <unsigned int> digits; // digits. Static unsigned int const base = 10000; // base number. Static unsigned int const width = 4; // digital width .}; // Reload the output symbol <. Ostream & operator <(ostream & OS, const integer & number) {OS <number. digits [number. digits. size ()-1]; for (INT I = number. digits. size ()-2; I> = 0; I --) OS <SETW (number. width) <setfill ('0') <number. digits [I]; return OS;} // remove the leading 0 produced by the large number operation. Void INTEGER: zero_justify (void) {for (INT I = digits. size ()-1; I> = 1; I --) {If (digits [I] = 0) digits. erase (digits. begin () + I); elsebreak;} integer & INTEGER: Operator * = (const integer & B) {return * This = * This * B ;} // multiply the large number by the unsigned integer. Integer & INTEGER: Operator * = (unsigned int B) {If (B> = base) {* This * = INTEGER (B); return * This ;} unsigned int carry = 0; For (INT I = 0; I <digits. size (); I ++) {digits [I] = digits [I] * B + carry; carry = digits [I]/base; digits [I] % = base;} If (carry) digits. push_back (carry); return * This;} // multiplication. Integer INTEGER: Operator * (const integer & B) {INTEGER C; // pre-allocate sufficient space. C. digits. resize (digits. size () + B. digits. size (); fill (C. digits. begin (), C. digits. end (), 0); // calculates the number of rows and adds them one by one. For (INT I = 0; I <B. digits. size (); I ++) for (Int J = 0; j <digits. size (); j ++) {C. digits [I + J] + = digits [J] * B. digits [I]; C. digits [I + J + 1] + = C. digits [I + J]/base; C. digits [I + J] % = base;} // remove the leading 0. C. zero_justify (); Return C;} // checks whether B * v <= row is true. If yes, true is returned. Otherwise, false is returned. Bool INTEGER: less_equal (integer & B, unsigned Int & V, integer & Row) {// The row is related to this question. digits. size () = B. digits. size () + 1, so it can be used. // If the maximum bit of B * V is greater than Row, you can confirm that B * V> row. Int carry = B. digits [B. digits. size ()-1] * V; If (carry/base)> row. digits [row. digits. size ()-1]) return false; // compare by bit. When two digits are not equal, record the comparison result, the last comparison result determines the size/relationship between B * V and row. Bool flag = true; carry = 0; For (INT I = 0; I <B. digits. size (); I ++) {int TMP = B. digits [I] * V + carry; carry = tmp/base; TMP % = base; If (row. digits [I]! = TMP) Flag = TMP <row. digits [I];} // The carry must be compared with the highest bit of the row. If (carry! = Row. digits [row. digits. size ()-1]) Flag = carry <row. digits [row. digits. size ()-1]; return flag;} // division. Use the bipartite method to obtain the operator. Integer INTEGER: Operator/(integer & B) {INTEGER C; integer row; // you need to allocate storage space for the quotient C and the row indicating the row to be reduced. C. digits. resize (digits. size ()-B. digits. size () + 1); row. digits. resize (B. digits. size () + 1); // initialization value. Fill (C. digits. begin (), C. digits. end (), 0); fill (row. digits. begin (), row. digits. end (), 0); For (INT I = digits. size ()-1; I> = 0; I --) {// obtain the dividend. For (Int J = row. digits. size ()-1; j> 0; j --) Row. digits [J] = row. digits [J-1]; row. digits [0] = digits [I]; // obtain the operator of the corresponding digit through the division of the binary test. Int high = base-1; int low = 0; unsigned int v = (high + low + 1)> 1; while (high> LOW) {If (less_equal (B, v, row) Low = V; elsehigh = V-1; V = (high + low + 1)> 1;} // subtract v B from the row. Int borrow, start = 0; For (; Start <B. digits. Size (); Start ++) {// determines the number of bits. Int T = row. digits [start]-V * B. digits [start]; If (T <0) borrow = (base-1-T)/base; elseborrow = 0; // high minus the number of bits. Row. digits [start + 1]-= borrow; // Add a bid to the low position. T + = base * borrow; row. digits [start] = T % base;} // store the corresponding operator in the result. For (Int J = C. digits. size ()-1; j> 0; j --) C. digits [J] = C. digits [J-1]; C. digits [0] = V;} // clear the leading 0. C. zero_justify (); Return C ;}# define treedeepth 22 // Number of labeling schemes with the branch factor K and depth D. Void cal_tree (vector <int> kD) {// number of the total number of K forks that store branch factors as K and depth as D. Integer tree [treedeepth] [treedeepth]; // number of nodes in which the storage branch factor is K and the depth is D. Unsigned int nodes [treedeepth] [treedeepth]; // calculate the number of nodes in the tree that meets K * D <= 21. And find the maximum number of nodes. Unsigned int max = 0; For (INT I = 0; I <kD. size (); I + = 2) {nodes [KD [I] [0] = 1; for (Int J = 1; j <= KD [I + 1]; j ++) {nodes [KD [I] [J] = nodes [KD [I] [J-1] * KD [I] + 1; if (nodes [KD [I] [J]> MAX) max = nodes [KD [I] [J];} // calculate the factorial from 1 to the number of nodes max-1. Vector <integer> fact (max); fact [0] = INTEGER (1); For (unsigned int I = 1; I <Max; I ++) fact [I] = fact [I-1] * I; // calculate the number of label schemes based on the simplified formula (5. For (INT I = 0; I <kD. size (); I + = 2) {If (tree [KD [I] [KD [I + 1]. is_zero () {// calculate n (K, M) ^ (K ^ (D-M), V = K ^ (D-m ). Unsigned int v = 1; integer T (1); For (INT d = KD [I + 1]; D> 0; d --) {v * = KD [I]; for (int K = 1; k <= V; k ++) T * = nodes [KD [I] [d-1];} tree [KD [I] [KD [I + 1] = fact [nodes [KD [I] [KD [I + 1]-1]/t ;} cout <tree [KD [I] [KD [I + 1] <Endl ;}} int main (INT AC, char * AV []) {int K, d; vector <int> KD; while (CIN> K> d) {kD. push_back (k); kD. push_back (d);} cal_tree (KD); Return 0 ;}